inital check in
22
manage.py
Executable file
@@ -0,0 +1,22 @@
|
||||
#!/usr/bin/env python
|
||||
"""Django's command-line utility for administrative tasks."""
|
||||
import os
|
||||
import sys
|
||||
|
||||
|
||||
def main():
|
||||
"""Run administrative tasks."""
|
||||
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'scha.settings')
|
||||
try:
|
||||
from django.core.management import execute_from_command_line
|
||||
except ImportError as exc:
|
||||
raise ImportError(
|
||||
"Couldn't import Django. Are you sure it's installed and "
|
||||
"available on your PYTHONPATH environment variable? Did you "
|
||||
"forget to activate a virtual environment?"
|
||||
) from exc
|
||||
execute_from_command_line(sys.argv)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
4
requirements.txt
Normal file
@@ -0,0 +1,4 @@
|
||||
stripe
|
||||
django
|
||||
django-adminplus
|
||||
django-recaptcha
|
||||
0
scha/__init__.py
Normal file
16
scha/asgi.py
Normal file
@@ -0,0 +1,16 @@
|
||||
"""
|
||||
ASGI config for scha project.
|
||||
|
||||
It exposes the ASGI callable as a module-level variable named ``application``.
|
||||
|
||||
For more information on this file, see
|
||||
https://docs.djangoproject.com/en/4.2/howto/deployment/asgi/
|
||||
"""
|
||||
|
||||
import os
|
||||
|
||||
from django.core.asgi import get_asgi_application
|
||||
|
||||
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'scha.settings')
|
||||
|
||||
application = get_asgi_application()
|
||||
133
scha/settings.py
Normal file
@@ -0,0 +1,133 @@
|
||||
"""
|
||||
Django settings for scha project.
|
||||
|
||||
Generated by 'django-admin startproject' using Django 4.2.10.
|
||||
|
||||
For more information on this file, see
|
||||
https://docs.djangoproject.com/en/4.2/topics/settings/
|
||||
|
||||
For the full list of settings and their values, see
|
||||
https://docs.djangoproject.com/en/4.2/ref/settings/
|
||||
"""
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
# Build paths inside the project like this: BASE_DIR / 'subdir'.
|
||||
BASE_DIR = Path(__file__).resolve().parent.parent
|
||||
|
||||
|
||||
# Quick-start development settings - unsuitable for production
|
||||
# See https://docs.djangoproject.com/en/4.2/howto/deployment/checklist/
|
||||
|
||||
# SECURITY WARNING: keep the secret key used in production secret!
|
||||
SECRET_KEY = 'django-insecure-0&6)5#t(wghsn$q7pg#s!x+_!s_y#labf6dh*8q%34q25iuag*'
|
||||
|
||||
# SECURITY WARNING: don't run with debug turned on in production!
|
||||
DEBUG = True
|
||||
|
||||
ALLOWED_HOSTS = []
|
||||
|
||||
|
||||
# Application definition
|
||||
|
||||
INSTALLED_APPS = [
|
||||
'schasite.apps.SchasiteConfig',
|
||||
'django.contrib.admin',
|
||||
'django.contrib.auth',
|
||||
'django.contrib.contenttypes',
|
||||
'django.contrib.sessions',
|
||||
'django.contrib.messages',
|
||||
'django.contrib.staticfiles',
|
||||
'phonenumber_field',
|
||||
'django_recaptcha',
|
||||
]
|
||||
|
||||
MIDDLEWARE = [
|
||||
'django.middleware.security.SecurityMiddleware',
|
||||
'django.contrib.sessions.middleware.SessionMiddleware',
|
||||
'django.middleware.common.CommonMiddleware',
|
||||
'django.middleware.csrf.CsrfViewMiddleware',
|
||||
'django.contrib.auth.middleware.AuthenticationMiddleware',
|
||||
'django.contrib.messages.middleware.MessageMiddleware',
|
||||
'django.middleware.clickjacking.XFrameOptionsMiddleware',
|
||||
]
|
||||
|
||||
ROOT_URLCONF = 'scha.urls'
|
||||
|
||||
TEMPLATES = [
|
||||
{
|
||||
'BACKEND': 'django.template.backends.django.DjangoTemplates',
|
||||
'DIRS': [],
|
||||
'APP_DIRS': True,
|
||||
'OPTIONS': {
|
||||
'context_processors': [
|
||||
'django.template.context_processors.debug',
|
||||
'django.template.context_processors.request',
|
||||
'django.contrib.auth.context_processors.auth',
|
||||
'django.contrib.messages.context_processors.messages',
|
||||
],
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
WSGI_APPLICATION = 'scha.wsgi.application'
|
||||
|
||||
|
||||
# Database
|
||||
# https://docs.djangoproject.com/en/4.2/ref/settings/#databases
|
||||
|
||||
DATABASES = {
|
||||
'default': {
|
||||
'ENGINE': 'django.db.backends.sqlite3',
|
||||
'NAME': BASE_DIR / 'db.sqlite3',
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
# Password validation
|
||||
# https://docs.djangoproject.com/en/4.2/ref/settings/#auth-password-validators
|
||||
|
||||
AUTH_PASSWORD_VALIDATORS = [
|
||||
{
|
||||
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
|
||||
},
|
||||
{
|
||||
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
|
||||
},
|
||||
{
|
||||
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
|
||||
},
|
||||
{
|
||||
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
|
||||
},
|
||||
]
|
||||
|
||||
|
||||
# Internationalization
|
||||
# https://docs.djangoproject.com/en/4.2/topics/i18n/
|
||||
|
||||
LANGUAGE_CODE = 'en-us'
|
||||
|
||||
TIME_ZONE = 'UTC'
|
||||
|
||||
USE_I18N = True
|
||||
|
||||
USE_TZ = True
|
||||
|
||||
|
||||
# Static files (CSS, JavaScript, Images)
|
||||
# https://docs.djangoproject.com/en/4.2/howto/static-files/
|
||||
|
||||
STATIC_URL = 'static/'
|
||||
|
||||
# Default primary key field type
|
||||
# https://docs.djangoproject.com/en/4.2/ref/settings/#default-auto-field
|
||||
|
||||
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
|
||||
STRIPE_PUBLISHABLE_KEY = 'pk_test_51OxENZDV0RPXOyxGkZnncLFbpVoQq6qxUSN08BPDTpHjrm2UTtvOrBG2A2IQhX3oxdYd6amGaci00SKchYZ5DUUN00jTBzhh62'
|
||||
STRIPE_SECRET_KEY = 'sk_test_51OxENZDV0RPXOyxGkULVr0MvVvXgNWsKjWiP54a9ls02LgsgXnzEwP0IQ0VjvP4Wt4RrPx1FvzHSbLvChQGOKvv800Ui0NBvIA'
|
||||
STRIPE_ENDPOINT_SECRET = 'whsec_a38b2d115b64d86713397e2718e2d42e5d263139dfbac6c0badc6f9ca8f72557'
|
||||
|
||||
# Recaptcha Stuff
|
||||
RECAPTCHA_PUBLIC_KEY = '6LesfrkpAAAAAGJ5vYp4KuuGcyfk70HkihCwp3d3'
|
||||
RECAPTCHA_PRIVATE_KEY = '6LesfrkpAAAAABCcDGli5cZiq1hfS0lfRiXg0mlI'
|
||||
30
scha/urls.py
Normal file
@@ -0,0 +1,30 @@
|
||||
"""
|
||||
URL configuration for scha project.
|
||||
|
||||
The `urlpatterns` list routes URLs to views. For more information please see:
|
||||
https://docs.djangoproject.com/en/4.2/topics/http/urls/
|
||||
Examples:
|
||||
Function views
|
||||
1. Add an import: from my_app import views
|
||||
2. Add a URL to urlpatterns: path('', views.home, name='home')
|
||||
Class-based views
|
||||
1. Add an import: from other_app.views import Home
|
||||
2. Add a URL to urlpatterns: path('', Home.as_view(), name='home')
|
||||
Including another URLconf
|
||||
1. Import the include() function: from django.urls import include, path
|
||||
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
|
||||
"""
|
||||
from django.contrib import admin
|
||||
from django.urls import include, path
|
||||
from django.conf.urls.static import static
|
||||
from django.conf import settings
|
||||
|
||||
from schasite.views import stripe_cancelled, stripe_success, stripe_webhook
|
||||
|
||||
urlpatterns = [
|
||||
path("schasite/", include("schasite.urls")),
|
||||
path('success/', stripe_success),
|
||||
path('cancelled/', stripe_cancelled),
|
||||
path('webhook/', stripe_webhook),
|
||||
path('admin/', admin.site.urls),
|
||||
] + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
|
||||
16
scha/wsgi.py
Normal file
@@ -0,0 +1,16 @@
|
||||
"""
|
||||
WSGI config for scha project.
|
||||
|
||||
It exposes the WSGI callable as a module-level variable named ``application``.
|
||||
|
||||
For more information on this file, see
|
||||
https://docs.djangoproject.com/en/4.2/howto/deployment/wsgi/
|
||||
"""
|
||||
|
||||
import os
|
||||
|
||||
from django.core.wsgi import get_wsgi_application
|
||||
|
||||
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'scha.settings')
|
||||
|
||||
application = get_wsgi_application()
|
||||
0
schasite/__init__.py
Normal file
192
schasite/admin.py
Normal file
@@ -0,0 +1,192 @@
|
||||
from django.contrib import admin
|
||||
from .models import UsefulLinks, Membership,CalendarEvent, MembershipServices, AddressModel1, MembershipPerson, MembershipCommittee, CalendarEventAddressModel, Payments
|
||||
from django.http import HttpResponse
|
||||
from datetime import datetime
|
||||
from .forms import PaymentImport
|
||||
# Register your models here.
|
||||
|
||||
class UsefulLinksAdmin(admin.ModelAdmin):
|
||||
list_display = ["name", "url"]
|
||||
|
||||
class MembershipAddressInline(admin.TabularInline):
|
||||
model = AddressModel1
|
||||
extra = 1
|
||||
readonly_fields = ('id',)
|
||||
|
||||
class MembershipPersonInline(admin.TabularInline):
|
||||
model = MembershipPerson
|
||||
extra = 1
|
||||
readonly_fields = ('id',)
|
||||
|
||||
class MembershipCommiteeInline(admin.TabularInline):
|
||||
model = MembershipCommittee
|
||||
extra = 1
|
||||
readonly_fields = ('id',)
|
||||
|
||||
class MembershipServicesInline(admin.TabularInline):
|
||||
model = MembershipServices
|
||||
extra = 1
|
||||
readonly_fields = ('id',)
|
||||
|
||||
def download_csv_by_members(modelAdmin, request, queryset):
|
||||
import csv
|
||||
import io as StringIO
|
||||
def stream_csv(queryset):
|
||||
csvfile = StringIO.StringIO()
|
||||
writer = csv.writer(csvfile)
|
||||
writer.writerow([
|
||||
'address_1',
|
||||
'city',
|
||||
'state',
|
||||
'zip_code',
|
||||
'first_name',
|
||||
'last_name',
|
||||
'email',
|
||||
'phone_number'
|
||||
])
|
||||
for q in queryset:
|
||||
people = [item for item in MembershipPerson.objects.filter(membership_id=q.id)]
|
||||
for person in people:
|
||||
writer.writerow([
|
||||
q.addressmodel1.address_1,
|
||||
q.addressmodel1.city,
|
||||
q.addressmodel1.state,
|
||||
q.addressmodel1.zip_code,
|
||||
person.first_name,
|
||||
person.last_name,
|
||||
person.email,
|
||||
person.phone_number
|
||||
])
|
||||
yield csvfile.getvalue()
|
||||
|
||||
now = datetime.now()
|
||||
filename = now.strftime("%Y_%m_%d_%H_%M_%S") + "_scha_member_by_member.csv"
|
||||
response = HttpResponse(stream_csv(queryset), content_type="text/csv")
|
||||
response['Content-Disposition'] = "attachment; filename={}".format(filename)
|
||||
return response
|
||||
|
||||
|
||||
def download_csv_by_address(modeladmin, request, queryset):
|
||||
import csv
|
||||
import io as StringIO
|
||||
def stream_csv(queryset):
|
||||
csvfile = StringIO.StringIO()
|
||||
writer = csv.writer(csvfile)
|
||||
writer.writerow(['address_1',
|
||||
"city",
|
||||
"state",
|
||||
"zip_code",
|
||||
"person_1_email",
|
||||
"person_1_phone",
|
||||
"person_1_first_name",
|
||||
"person_1_last_name",
|
||||
"person_2_email",
|
||||
"person_2_phone",
|
||||
"person_2_first_name",
|
||||
"person_2_last_name"])
|
||||
|
||||
for q in queryset:
|
||||
people = [item for item in MembershipPerson.objects.filter(membership_id=q.id)]
|
||||
writer.writerow([
|
||||
q.addressmodel1.address_1,
|
||||
q.addressmodel1.city,
|
||||
q.addressmodel1.state,
|
||||
q.addressmodel1.zip_code,
|
||||
people[0].email if len(people) > 0 else "",
|
||||
people[0].phone_number if len(people) > 0 else "",
|
||||
people[0].first_name if len(people) > 0 else "",
|
||||
people[0].last_name if len(people) > 0 else "",
|
||||
people[1].email if len(people) > 1 else "",
|
||||
people[1].phone_number if len(people) > 1 else "",
|
||||
people[1].first_name if len(people) > 1 else "",
|
||||
people[1].last_name if len(people) > 1 else "",
|
||||
])
|
||||
yield csvfile.getvalue()
|
||||
|
||||
now = datetime.now()
|
||||
filename = now.strftime("%Y_%m_%d_%H_%M_%S") + "_scha_member_by_address.csv"
|
||||
response = HttpResponse(stream_csv(queryset), content_type="text/csv")
|
||||
response['Content-Disposition'] = "attachment; filename={}".format(filename)
|
||||
return response
|
||||
|
||||
class MembershipAdmin(admin.ModelAdmin):
|
||||
inlines = [MembershipAddressInline, MembershipPersonInline, MembershipCommiteeInline, MembershipServicesInline]
|
||||
actions=[download_csv_by_address, download_csv_by_members]
|
||||
|
||||
class CalendarEventAddressInline(admin.TabularInline):
|
||||
model = CalendarEventAddressModel
|
||||
extra = 1
|
||||
readonly_fields = ('id',)
|
||||
|
||||
class CalendarEventAdmin(admin.ModelAdmin):
|
||||
inlines = [CalendarEventAddressInline]
|
||||
list_display = ["event_name", "start_date", "end_date", "coordinator_email", "event_link_name"]
|
||||
|
||||
class AddressModelAdmin(admin.ModelAdmin):
|
||||
pass
|
||||
|
||||
class MembershipPersonAdmin(admin.ModelAdmin):
|
||||
pass
|
||||
|
||||
class MembershipCommitteeAdmin(admin.ModelAdmin):
|
||||
pass
|
||||
|
||||
class MembershipServicesAdmin(admin.ModelAdmin):
|
||||
pass
|
||||
|
||||
class CalendarEventAddressModelAdmin(admin.ModelAdmin):
|
||||
pass
|
||||
|
||||
def download_payments(modelAdmin, request, queryset):
|
||||
import csv
|
||||
import io as StringIO
|
||||
def stream_payment_csv(queryset):
|
||||
csvfile = StringIO.StringIO()
|
||||
writer = csv.writer(csvfile)
|
||||
writer.writerow([
|
||||
'email',
|
||||
'date',
|
||||
'status',
|
||||
'first_name',
|
||||
'last_name',
|
||||
'phone_number'
|
||||
])
|
||||
for q in queryset:
|
||||
first_name=""
|
||||
last_name = ""
|
||||
phone_number = ""
|
||||
if q.person:
|
||||
first_name = q.person.first_name if q.person.first_name else ""
|
||||
last_name = q.person.last_name if q.person.last_name else ""
|
||||
phone_number = q.person.phone_number if q.person.phone_number else ""
|
||||
writer.writerow([
|
||||
q.email,
|
||||
q.date,
|
||||
q.status,
|
||||
first_name,
|
||||
last_name,
|
||||
phone_number,
|
||||
])
|
||||
yield csvfile.getvalue()
|
||||
|
||||
now = datetime.now()
|
||||
filename = now.strftime("%Y_%m_%d_%H_%M_%S") + "_scha_payments_by_member.csv"
|
||||
response = HttpResponse(stream_payment_csv(queryset), content_type="text/csv")
|
||||
response['Content-Disposition'] = "attachment; filename={}".format(filename)
|
||||
return response
|
||||
|
||||
class PaymentsAdmin(admin.ModelAdmin):
|
||||
list_display = ["date", "status", "email"]
|
||||
search_fields = ['email']
|
||||
actions=[download_payments]
|
||||
form = PaymentImport
|
||||
|
||||
admin.site.register(UsefulLinks, UsefulLinksAdmin)
|
||||
admin.site.register(Membership, MembershipAdmin)
|
||||
admin.site.register(CalendarEvent, CalendarEventAdmin)
|
||||
admin.site.register(AddressModel1, AddressModelAdmin)
|
||||
admin.site.register(MembershipPerson, MembershipPersonAdmin)
|
||||
admin.site.register(MembershipCommittee, MembershipCommitteeAdmin)
|
||||
admin.site.register(MembershipServices, MembershipServicesAdmin)
|
||||
admin.site.register(CalendarEventAddressModel, CalendarEventAddressModelAdmin)
|
||||
admin.site.register(Payments, PaymentsAdmin)
|
||||
6
schasite/apps.py
Normal file
@@ -0,0 +1,6 @@
|
||||
from django.apps import AppConfig
|
||||
|
||||
|
||||
class SchasiteConfig(AppConfig):
|
||||
default_auto_field = 'django.db.models.BigAutoField'
|
||||
name = 'schasite'
|
||||
101
schasite/forms.py
Normal file
@@ -0,0 +1,101 @@
|
||||
from django import forms
|
||||
from django.forms import ModelForm
|
||||
from .models import Membership, AddressModel1, MembershipPerson, MembershipCommittee, MembershipServices
|
||||
from phonenumber_field.formfields import PhoneNumberField
|
||||
from django.core.exceptions import ValidationError
|
||||
# from django_recaptcha.fields import ReCaptchaField
|
||||
# from django.conf import settings
|
||||
# from django_recaptcha.widgets import ReCaptchaV3
|
||||
|
||||
# class CaptchaForm(forms.Form):
|
||||
# captcha = ReCaptchaField(
|
||||
# public_key=settings.RECAPTCHA_PUBLIC_KEY,
|
||||
# private_key=settings.RECAPTCHA_PRIVATE_KEY,
|
||||
# widget=ReCaptchaV3(
|
||||
# attrs={
|
||||
# 'required_score':0.85,
|
||||
# }
|
||||
# ),
|
||||
|
||||
# )
|
||||
|
||||
class ChildrenForm(ModelForm):
|
||||
class Meta:
|
||||
model = Membership
|
||||
fields = ["children"]
|
||||
|
||||
class AddressForm(ModelForm):
|
||||
class Meta:
|
||||
model = AddressModel1
|
||||
fields = ["address_1","address_2","city","state","zip_code"]
|
||||
|
||||
class PeopleForm(ModelForm):
|
||||
phone_number = PhoneNumberField(required=False)
|
||||
|
||||
def clean(self):
|
||||
cleaned_data = super().clean()
|
||||
if cleaned_data.get('phone_number'):
|
||||
if len(cleaned_data.get('first_name')) == 0 or len(cleaned_data.get('last_name')) == 0 or len(cleaned_data.get('email')) == 0 or len(cleaned_data.get('phone_number').raw_input) == 0:
|
||||
raise ValidationError ('A Field is missing')
|
||||
else:
|
||||
raise ValidationError('No phone number provided')
|
||||
|
||||
class Meta:
|
||||
model = MembershipPerson
|
||||
fields = ["first_name","last_name","phone_number","email"]
|
||||
|
||||
class CommitteeForm(ModelForm):
|
||||
block_captain = forms.BooleanField(label="I can serve as a Block Captain (distribute newsletters & directories)", required=False)
|
||||
coordinator = forms.BooleanField(label="I can serve as a Coordinator, SCHA Board Member Position (oversee & organize block captains)", required=False)
|
||||
egg_hunt = forms.BooleanField(label="Easter Egg Hunt (late March)", required=False)
|
||||
spring_garage_sale = forms.BooleanField(label="Spring Garage Sale (May/June)", required=False)
|
||||
golf_outing = forms.BooleanField(label="Golf Outing (Summer)", required=False)
|
||||
ice_cream_social = forms.BooleanField(label="Ice Creame Social (August)", required=False)
|
||||
fall_garage_sale = forms.BooleanField(label="Fall Garage Sale (September/October)", required=False)
|
||||
halloween_party = forms.BooleanField(label="Halloween Party (October)", required=False)
|
||||
santa_visit = forms.BooleanField(label="Santa Visits (December)", required=False)
|
||||
website = forms.BooleanField(label="SCHA Newsletter/Website (wite articles, edit, report, etc)", required=False)
|
||||
civic_affair = forms.BooleanField(label="Civic Affairs Journalist (report on school board/city council mtgs)", required=False)
|
||||
phone_directory = forms.BooleanField(label="Annual Phone Directory (Help compile, edit, produce our Annual Neighborhood Directory)", required=False)
|
||||
no_preference = forms.BooleanField(label="No Preference. I want to help in some way . Please email me.", required=False)
|
||||
class Meta:
|
||||
model = MembershipCommittee
|
||||
fields = [
|
||||
"block_captain",
|
||||
"coordinator",
|
||||
"egg_hunt",
|
||||
"spring_garage_sale",
|
||||
"golf_outing",
|
||||
"ice_cream_social",
|
||||
"fall_garage_sale",
|
||||
"halloween_party",
|
||||
"santa_visit",
|
||||
"website",
|
||||
"civic_affair",
|
||||
"phone_directory",
|
||||
"no_preference",
|
||||
]
|
||||
|
||||
class ServicesForm(ModelForm):
|
||||
babysitting = forms.BooleanField(label="Babysitting", required=False)
|
||||
lawn_mowing = forms.BooleanField(label="Lawn Mowing", required=False)
|
||||
snow_shoveling = forms.BooleanField(label="Snow Shoveling", required=False)
|
||||
leaf_raking = forms.BooleanField(label="Leaf Raking", required=False)
|
||||
petsitting = forms.BooleanField(label="Petsitting", required=False)
|
||||
house_sitting = forms.BooleanField(label="Housesitting", required=False)
|
||||
other = forms.BooleanField(label="Other", required=False)
|
||||
class Meta:
|
||||
model = MembershipServices
|
||||
fields = [
|
||||
"babysitting",
|
||||
"lawn_mowing",
|
||||
"snow_shoveling",
|
||||
"leaf_raking",
|
||||
"petsitting",
|
||||
"house_sitting",
|
||||
"other",
|
||||
"other_desc",
|
||||
]
|
||||
|
||||
class PaymentImport(ModelForm):
|
||||
pass
|
||||
99
schasite/migrations/0001_initial.py
Normal file
@@ -0,0 +1,99 @@
|
||||
# Generated by Django 4.2.10 on 2024-03-20 13:28
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
import phonenumber_field.modelfields
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
initial = True
|
||||
|
||||
dependencies = [
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='AddressModel',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('address_1', models.CharField(max_length=128)),
|
||||
('address_2', models.CharField(blank=True, max_length=128)),
|
||||
('city', models.CharField(max_length=128)),
|
||||
('state', models.CharField(max_length=2)),
|
||||
('zip_code', models.CharField(max_length=5)),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Membership',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('children', models.CharField(default='', max_length=256)),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='UsefulLinks',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('name', models.CharField(max_length=256)),
|
||||
('url', models.CharField(max_length=256)),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='MembershipPerson',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('first_name', models.CharField(blank=True, max_length=256, null=True)),
|
||||
('last_name', models.CharField(blank=True, max_length=256, null=True)),
|
||||
('phone_number', phonenumber_field.modelfields.PhoneNumberField(max_length=128, null=True, region=None, unique=True)),
|
||||
('email', models.EmailField(blank=True, max_length=254, null=True)),
|
||||
('membership', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='schasite.membership')),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='MembershipCommittee',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('block_captain', models.BooleanField(default=False)),
|
||||
('coordinator', models.BooleanField(default=False)),
|
||||
('egg_hunt', models.BooleanField(default=False)),
|
||||
('spring_garage_sale', models.BooleanField(default=False)),
|
||||
('golf_outing', models.BooleanField(default=False)),
|
||||
('ice_cream_social', models.BooleanField(default=False)),
|
||||
('fall_garage_sale', models.BooleanField(default=False)),
|
||||
('halloween_party', models.BooleanField(default=False)),
|
||||
('santa_visit', models.BooleanField(default=False)),
|
||||
('website', models.BooleanField(default=False)),
|
||||
('civic_affair', models.BooleanField(default=False)),
|
||||
('phone_directory', models.BooleanField(default=False)),
|
||||
('no_preference', models.BooleanField(default=False)),
|
||||
('membership', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to='schasite.membership')),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='CalendarEvent',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('event_name', models.CharField(max_length=256)),
|
||||
('start_date', models.DateField(blank=True, null=True)),
|
||||
('end_date', models.DateField(blank=True, null=True)),
|
||||
('location_name', models.CharField(blank=True, max_length=256, null=True)),
|
||||
('coordinator_email', models.EmailField(blank=True, max_length=256, null=True)),
|
||||
('event_link_name', models.CharField(blank=True, max_length=64, null=True)),
|
||||
('event_url', models.URLField(blank=True, max_length=256, null=True)),
|
||||
('location_address', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='schasite.addressmodel')),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='AddressModel1',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('address_1', models.CharField(max_length=128)),
|
||||
('address_2', models.CharField(blank=True, max_length=128)),
|
||||
('city', models.CharField(max_length=128)),
|
||||
('state', models.CharField(max_length=2)),
|
||||
('zip_code', models.CharField(max_length=5)),
|
||||
('membership', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to='schasite.membership')),
|
||||
],
|
||||
),
|
||||
]
|
||||
18
schasite/migrations/0002_alter_membership_children.py
Normal file
@@ -0,0 +1,18 @@
|
||||
# Generated by Django 4.2.10 on 2024-03-20 15:13
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('schasite', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='membership',
|
||||
name='children',
|
||||
field=models.CharField(blank=True, default='', max_length=256, null=True),
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,78 @@
|
||||
# Generated by Django 4.2.10 on 2024-03-20 15:13
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('schasite', '0002_alter_membership_children'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='membershipcommittee',
|
||||
name='block_captain',
|
||||
field=models.BooleanField(blank=True, default=False, null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='membershipcommittee',
|
||||
name='civic_affair',
|
||||
field=models.BooleanField(blank=True, default=False, null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='membershipcommittee',
|
||||
name='coordinator',
|
||||
field=models.BooleanField(blank=True, default=False, null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='membershipcommittee',
|
||||
name='egg_hunt',
|
||||
field=models.BooleanField(blank=True, default=False, null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='membershipcommittee',
|
||||
name='fall_garage_sale',
|
||||
field=models.BooleanField(blank=True, default=False, null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='membershipcommittee',
|
||||
name='golf_outing',
|
||||
field=models.BooleanField(blank=True, default=False, null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='membershipcommittee',
|
||||
name='halloween_party',
|
||||
field=models.BooleanField(blank=True, default=False, null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='membershipcommittee',
|
||||
name='ice_cream_social',
|
||||
field=models.BooleanField(blank=True, default=False, null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='membershipcommittee',
|
||||
name='no_preference',
|
||||
field=models.BooleanField(blank=True, default=False, null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='membershipcommittee',
|
||||
name='phone_directory',
|
||||
field=models.BooleanField(blank=True, default=False, null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='membershipcommittee',
|
||||
name='santa_visit',
|
||||
field=models.BooleanField(blank=True, default=False, null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='membershipcommittee',
|
||||
name='spring_garage_sale',
|
||||
field=models.BooleanField(blank=True, default=False, null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='membershipcommittee',
|
||||
name='website',
|
||||
field=models.BooleanField(blank=True, default=False, null=True),
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,19 @@
|
||||
# Generated by Django 4.2.10 on 2024-03-22 13:40
|
||||
|
||||
from django.db import migrations
|
||||
import phonenumber_field.modelfields
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('schasite', '0003_alter_membershipcommittee_block_captain_and_more'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='membershipperson',
|
||||
name='phone_number',
|
||||
field=phonenumber_field.modelfields.PhoneNumberField(max_length=128, null=True, region=None),
|
||||
),
|
||||
]
|
||||
29
schasite/migrations/0005_membershipservices.py
Normal file
@@ -0,0 +1,29 @@
|
||||
# Generated by Django 4.2.10 on 2024-03-22 14:07
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('schasite', '0004_alter_membershipperson_phone_number'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='MembershipServices',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('babysitting', models.BooleanField(blank=True, default=False, null=True)),
|
||||
('lawn_mowing', models.BooleanField(blank=True, default=False, null=True)),
|
||||
('snow_shoveling', models.BooleanField(blank=True, default=False, null=True)),
|
||||
('leaf_raking', models.BooleanField(blank=True, default=False, null=True)),
|
||||
('petsitting', models.BooleanField(blank=True, default=False, null=True)),
|
||||
('house_sitting', models.BooleanField(blank=True, default=False, null=True)),
|
||||
('other', models.BooleanField(blank=True, default=False, null=True)),
|
||||
('other_desc', models.CharField(blank=True, default='', max_length=256, null=True)),
|
||||
('membership', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to='schasite.membership')),
|
||||
],
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,37 @@
|
||||
# Generated by Django 4.2.10 on 2024-03-23 18:03
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('schasite', '0005_membershipservices'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='CalendarEventAddressModel',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('address_1', models.CharField(max_length=128)),
|
||||
('address_2', models.CharField(blank=True, max_length=128)),
|
||||
('city', models.CharField(max_length=128)),
|
||||
('state', models.CharField(max_length=2)),
|
||||
('zip_code', models.CharField(max_length=5)),
|
||||
],
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='calendarevent',
|
||||
name='location_address',
|
||||
),
|
||||
migrations.DeleteModel(
|
||||
name='AddressModel',
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='calendareventaddressmodel',
|
||||
name='calendar_event',
|
||||
field=models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to='schasite.calendarevent'),
|
||||
),
|
||||
]
|
||||
25
schasite/migrations/0007_payments.py
Normal file
@@ -0,0 +1,25 @@
|
||||
# Generated by Django 4.2.10 on 2024-03-27 17:40
|
||||
|
||||
import datetime
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('schasite', '0006_calendareventaddressmodel_and_more'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='Payments',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('date', models.DateField(default=datetime.datetime(2024, 3, 27, 17, 40, 28, 908036))),
|
||||
('status', models.CharField(default='Completed', max_length=256)),
|
||||
('email', models.EmailField(blank=True, max_length=254, null=True)),
|
||||
('person', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='schasite.membershipperson')),
|
||||
],
|
||||
),
|
||||
]
|
||||
19
schasite/migrations/0008_alter_payments_date.py
Normal file
@@ -0,0 +1,19 @@
|
||||
# Generated by Django 4.2.10 on 2024-03-27 17:41
|
||||
|
||||
import datetime
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('schasite', '0007_payments'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='payments',
|
||||
name='date',
|
||||
field=models.DateField(default=datetime.datetime(2024, 3, 27, 17, 41, 22, 742260, tzinfo=datetime.timezone.utc)),
|
||||
),
|
||||
]
|
||||
0
schasite/migrations/__init__.py
Normal file
128
schasite/models.py
Normal file
@@ -0,0 +1,128 @@
|
||||
from django.db import models
|
||||
from phonenumber_field.modelfields import PhoneNumberField
|
||||
import datetime
|
||||
from django.utils import timezone
|
||||
|
||||
|
||||
# Create your models here.
|
||||
class UsefulLinks(models.Model):
|
||||
name = models.CharField(max_length=256)
|
||||
url = models.CharField(max_length=256)
|
||||
|
||||
|
||||
class Membership(models.Model):
|
||||
children = models.CharField(max_length=256, default="", blank=True, null=True)
|
||||
|
||||
def get_address_str(self):
|
||||
if self.addressmodel1 is None:
|
||||
return "No Address"
|
||||
elif self.addressmodel1.address_1 is None:
|
||||
return "No Address"
|
||||
else:
|
||||
return self.addressmodel1.address_1
|
||||
|
||||
def get_person_1(self):
|
||||
emails = [item.email for item in MembershipPerson.objects.filter(membership_id=self.id)]
|
||||
# remove all the Nones
|
||||
filtered_emails = [i for i in emails if i is not None]
|
||||
if len(filtered_emails) == 0:
|
||||
return "No Person"
|
||||
else:
|
||||
return " | ".join(filtered_emails)
|
||||
|
||||
def __str__(self):
|
||||
return self.get_address_str() + " | " + self.get_person_1()
|
||||
|
||||
class AddressModel1(models.Model):
|
||||
membership = models.OneToOneField(Membership, on_delete=models.CASCADE)
|
||||
address_1 = models.CharField(max_length=128)
|
||||
address_2 = models.CharField(max_length=128, blank=True)
|
||||
city = models.CharField(max_length=128)
|
||||
state = models.CharField(max_length=2)
|
||||
zip_code = models.CharField(max_length=5)
|
||||
|
||||
|
||||
|
||||
class CalendarEvent(models.Model):
|
||||
event_name = models.CharField(max_length=256)
|
||||
start_date = models.DateField(blank=True, null=True)
|
||||
end_date = models.DateField(blank=True, null=True)
|
||||
location_name = models.CharField(max_length=256, blank=True, null=True)
|
||||
coordinator_email = models.EmailField(max_length=256, blank=True, null=True)
|
||||
event_link_name = models.CharField(max_length=64, blank=True, null=True)
|
||||
event_url = models.URLField(max_length=256, blank=True, null=True)
|
||||
|
||||
def has_date(self):
|
||||
return not self.start_date is None
|
||||
|
||||
def past_event(self):
|
||||
if self.has_date():
|
||||
return self.start_date <= datetime.datetime.now().date()
|
||||
else:
|
||||
return False
|
||||
|
||||
def future_event(self):
|
||||
if self.has_date():
|
||||
return self.start_date > datetime.datetime.now().date()
|
||||
else:
|
||||
return False
|
||||
|
||||
def no_date(self):
|
||||
return not self.has_date()
|
||||
|
||||
class CalendarEventAddressModel(models.Model):
|
||||
calendar_event = models.OneToOneField(CalendarEvent, on_delete=models.CASCADE)
|
||||
address_1 = models.CharField(max_length=128)
|
||||
address_2 = models.CharField(max_length=128, blank=True)
|
||||
city = models.CharField(max_length=128)
|
||||
state = models.CharField(max_length=2)
|
||||
zip_code = models.CharField(max_length=5)
|
||||
|
||||
def __str__ (self):
|
||||
return self.address_1 + ", " + self.city + ", " + self.state + " " + self.zip_code
|
||||
|
||||
class MembershipPerson(models.Model):
|
||||
membership = models.ForeignKey(Membership, on_delete=models.CASCADE, blank=True, null=True)
|
||||
first_name = models.CharField(max_length=256, blank=True, null=True)
|
||||
last_name = models.CharField(max_length=256, blank=True, null=True)
|
||||
phone_number = PhoneNumberField(blank=False, null=True)
|
||||
email = models.EmailField(max_length=254, blank=True, null=True)
|
||||
|
||||
def __str__(self):
|
||||
return self.email if self.email else "No email"
|
||||
|
||||
|
||||
|
||||
|
||||
class MembershipCommittee(models.Model):
|
||||
membership = models.OneToOneField(Membership, on_delete=models.CASCADE)
|
||||
block_captain = models.BooleanField(default=False, blank=True, null=True)
|
||||
coordinator = models.BooleanField(default=False, blank=True, null=True)
|
||||
egg_hunt = models.BooleanField(default=False, blank=True, null=True)
|
||||
spring_garage_sale = models.BooleanField(default=False, blank=True, null=True)
|
||||
golf_outing = models.BooleanField(default=False, blank=True, null=True)
|
||||
ice_cream_social = models.BooleanField(default=False, blank=True, null=True)
|
||||
fall_garage_sale = models.BooleanField(default=False, blank=True, null=True)
|
||||
halloween_party = models.BooleanField(default=False, blank=True, null=True)
|
||||
santa_visit = models.BooleanField(default=False, blank=True, null=True)
|
||||
website = models.BooleanField(default=False, blank=True, null=True)
|
||||
civic_affair = models.BooleanField(default=False, blank=True, null=True)
|
||||
phone_directory = models.BooleanField(default=False, blank=True, null=True)
|
||||
no_preference = models.BooleanField(default=False, blank=True, null=True)
|
||||
|
||||
class MembershipServices(models.Model):
|
||||
membership = models.OneToOneField(Membership, on_delete=models.CASCADE)
|
||||
babysitting = models.BooleanField(default=False, blank=True, null=True)
|
||||
lawn_mowing = models.BooleanField(default=False, blank=True, null=True)
|
||||
snow_shoveling = models.BooleanField(default=False, blank=True, null=True)
|
||||
leaf_raking = models.BooleanField(default=False, blank=True, null=True)
|
||||
petsitting = models.BooleanField(default=False, blank=True, null=True)
|
||||
house_sitting = models.BooleanField(default=False, blank=True, null=True)
|
||||
other = models.BooleanField(default=False, blank=True, null=True)
|
||||
other_desc = models.CharField(default="", blank=True, null=True, max_length=256)
|
||||
|
||||
class Payments(models.Model):
|
||||
date = models.DateField(default=timezone.now())
|
||||
status = models.CharField(default='Completed', max_length=256)
|
||||
email = models.EmailField(blank=True, null=True)
|
||||
person = models.ForeignKey(MembershipPerson, on_delete=models.CASCADE, blank=True,null=True)
|
||||
156
schasite/static/css/style.css
Normal file
@@ -0,0 +1,156 @@
|
||||
/* CSS Document */
|
||||
{% load static %}
|
||||
body{
|
||||
margin:0px;
|
||||
background-repeat: repeat;
|
||||
font-family:Verdana, Arial, Helvetica, sans-serif; font-size:12px;
|
||||
}
|
||||
a{color:#63880a;}
|
||||
h1{
|
||||
font-family:Arial, Helvetica, sans-serif; font-size:25px;
|
||||
color:#63880a; line-height:normal;
|
||||
margin:0px; padding:30px 0px 0px 0px;
|
||||
}
|
||||
h1 span{color:#979797;}
|
||||
.clear{margin:0px; padding:0px; clear:both;}
|
||||
.top-head{
|
||||
height:118px; width:1000px; margin:auto;
|
||||
background:url(../images/top-head.gif) repeat-x;
|
||||
}
|
||||
.logo{
|
||||
height:103px; width:325px;
|
||||
float:left; padding:15px 0px 0px 55px;
|
||||
}
|
||||
.right-top{
|
||||
height:83px; width:620px; float:left;
|
||||
padding:35px 0px 0px 0px;
|
||||
}
|
||||
.tag-line{
|
||||
height:auto; width:175px; float:left; padding:0px 10px 0px 20px;
|
||||
color:#8b8b8b; font-size:11px; font-family:Verdana, Arial, Helvetica, sans-serif;
|
||||
line-height:22px; border-left:#cad79f solid 1px; text-transform:uppercase; font-weight:bold;
|
||||
}
|
||||
.punch-line{
|
||||
height:auto; width:370px; float:left; padding:0px 20px 0px 20px;
|
||||
color:#4a4a4a; font-size:11px; font-family:Verdana, Arial, Helvetica, sans-serif;
|
||||
line-height:22px; border-left:#cad79f solid 1px; font-weight:bold; font-style:italic;
|
||||
}
|
||||
.punch-line a{color:#9db54e;}
|
||||
#header{
|
||||
height:279px; width:445px; margin:auto;
|
||||
background:url(../images/header.gif) no-repeat;
|
||||
padding:40px 500px 0px 55px;
|
||||
font-family:Verdana, Arial, Helvetica, sans-serif; color:#FFFFFF;
|
||||
font-size:23px; line-height:26px; font-weight:normal;
|
||||
}
|
||||
#header ul{margin:0px; padding:20px 0px 0px 20px;}
|
||||
#header ul li{
|
||||
font-family:Verdana, Arial, Helvetica, sans-serif; font-size:13px;
|
||||
color:#FFFFFF; font-weight:bold;
|
||||
}
|
||||
#header ul li a{color:#FFFFFF;}
|
||||
.nav-bar{
|
||||
height:56px; width:1000px; margin:auto;
|
||||
background:url(../images/nav-bar.gif) repeat-x;
|
||||
}
|
||||
.nav-bar ul{
|
||||
margin:0px;
|
||||
padding:0px 0px 0px 30px;
|
||||
list-style-type:none;
|
||||
}
|
||||
.nav-bar ul li{
|
||||
height:36px; width:auto; float:left;
|
||||
background:url(../images/list-left.gif) no-repeat;
|
||||
display:block;
|
||||
padding:20px 12px 0px 12px;
|
||||
}
|
||||
.nav-bar ul li a{
|
||||
font-family:Arial, Helvetica, sans-serif; font-size:14px; text-decoration:none;
|
||||
color:#FFFFFF;
|
||||
background:url(../images/list-arrow.gif) no-repeat;
|
||||
font-weight:normal;
|
||||
padding-left:22px; font-weight:bold;
|
||||
background-position: 6px;
|
||||
}
|
||||
.top-body{
|
||||
height:auto; width:940px; margin:auto;
|
||||
background: url(../images/top-body.gif) repeat-x #cfcfcf;
|
||||
padding:0px 0px 25px 60px;
|
||||
}
|
||||
.top-body-con{
|
||||
height:auto; width:265px; float:left;
|
||||
padding:0px 35px 0px 0px;
|
||||
}
|
||||
.top-body-con p{
|
||||
margin:0px; padding:30px 0px 0px 0px;
|
||||
font-family:Verdana, Arial, Helvetica, sans-serif; color:#2e2e2e;
|
||||
font-size:11px; font-weight:bold; line-height:26px;
|
||||
}
|
||||
.top-body-con a{color:#63880a;}
|
||||
.top-body-con span{color:#63880a; font-size:15px;}
|
||||
.img-box{
|
||||
height:auto; width:auto; float:left;
|
||||
padding:30px 25px 0px 0px;
|
||||
}
|
||||
.img-box-1{
|
||||
height:auto; width:auto; float:right;
|
||||
padding:20px 0px 0px 25px;
|
||||
}
|
||||
.mid-body{
|
||||
height:auto; width:890px; margin:auto;
|
||||
background:url(../images/mid-body.gif) repeat-x #FFFFFF;
|
||||
padding:0px 50px 30px 60px;
|
||||
}
|
||||
.mid-body p{
|
||||
margin:0px; padding:10px 0px 0px 0px;
|
||||
font-family:Verdana, Arial, Helvetica, sans-serif; color:#343434;
|
||||
font-size:14px; line-height:26px;
|
||||
}
|
||||
.mid-body a{color:#63880a;}
|
||||
.mid-body p span{color:#343434; font-size:17px;}
|
||||
.bt-cont{
|
||||
height:auto; width:930px; margin:auto;
|
||||
background:url(../images/rest-con.gif) repeat-x #e8edda;
|
||||
padding:0px 0px 20px 70px;
|
||||
}
|
||||
.cont-rl{
|
||||
height:auto; width:300px; float:left;
|
||||
}
|
||||
.bt-cont p{
|
||||
margin:0px; padding:30px 0px 0px 0px;
|
||||
font-family:Verdana, Arial, Helvetica, sans-serif; color:#2e2e2e;
|
||||
font-size:14px; line-height:30px;
|
||||
}
|
||||
.bt-cont a{color:#63880a;}
|
||||
.bt-cont span{color:#63880a; font-size:20px; font-weight:normal;}
|
||||
#footer{
|
||||
height:25px; width:880px; margin:auto;
|
||||
text-align:left; font-family:Verdana, Arial, Helvetica, sans-serif;
|
||||
color:#FFFFFF; font-size:11px; background:url(../images/footer.gif) repeat-x;
|
||||
padding:15px 60px 0px 60px;
|
||||
}
|
||||
#footer strong{
|
||||
float:right; color:#FFFFFF;
|
||||
}
|
||||
#footer a{ color:#FFFFFF; }
|
||||
|
||||
/* inner pages css start */
|
||||
h1.inner{font:33px Myriad Pro, Arial; color:#fff; font-weight:100; margin:0px; padding:25px 0px 10px 0px; background:none}
|
||||
.aboutus-img{float:right; border:4px solid #b0a48b; margin:0px 0px 10px 20px;}
|
||||
h5{font:15px Myriad Pro, Arial, Helvetica, sans-serif; color:#63880a; font-weight:bold; padding:0px 0px 5px 0px; border-bottom:1px dotted #666666; margin:0px 0px 10px 0px;}
|
||||
h6{font:17px Myriad Pro, Arial, Helvetica, sans-serif; color:#63880a; font-weight:bold; padding:0px 0px 5px 0px; margin:0px 0px 10px 0px;}
|
||||
.aboutcolumnzone{padding:20px 0px 16px 0px;}
|
||||
.aboutcolumn1{width:48%; float:left; margin:0px 0px 10px 0px;}
|
||||
.aboutcolumn2{width:48%; float:right; margin:0px 0px 10px 0px;}
|
||||
.abouticon{float:left; margin:0px 20px 0px 0px;}
|
||||
.insidereadmore{padding:10px 0px 10px 0px;}
|
||||
input.button{color:#ffffff; background:#414141; font:bold 11px Arial, Helvetica, sans-serif; text-decoration:none; padding:10px 10px; margin:0px 5px 5px 0; border:1px solid #000000;}
|
||||
input.button:hover{cursor:pointer; color:#cccccc;}
|
||||
.project-img{float:right; margin-left:20px; border: 6px solid #a1b96b;}
|
||||
.whiteheading{font:30px Myriad Pro, Arial; color:#ffffff; font-weight:100; padding:0px; margin:25px 0px 20px 0px;}
|
||||
.ourprojectrow{margin-bottom:20px; border-bottom:1px dotted #666666; padding-bottom:10px; width: 95%;}
|
||||
.servicecolumnzone{padding:20px 0px 16px 0px;}
|
||||
.servicecolumn1{width:48%; float:left; margin:0px 0px 10px 0px;}
|
||||
.servicecolumn2{width:48%; float:right; margin:0px 0px 10px 0px;}
|
||||
.blog-posted-row{padding:3px;}
|
||||
/* inner pages css ends */
|
||||
BIN
schasite/static/images/25.gif
Normal file
|
After Width: | Height: | Size: 2.6 KiB |
BIN
schasite/static/images/bricks.jpg
Normal file
|
After Width: | Height: | Size: 3.1 KiB |
BIN
schasite/static/images/dues.jpeg
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
schasite/static/images/easter.gif
Normal file
|
After Width: | Height: | Size: 3.1 KiB |
BIN
schasite/static/images/facebook.gif
Normal file
|
After Width: | Height: | Size: 2.0 KiB |
BIN
schasite/static/images/footer.gif
Normal file
|
After Width: | Height: | Size: 159 B |
BIN
schasite/static/images/garage_sale.gif
Normal file
|
After Width: | Height: | Size: 3.9 KiB |
BIN
schasite/static/images/header.gif
Normal file
|
After Width: | Height: | Size: 160 KiB |
BIN
schasite/static/images/jointoday.gif
Normal file
|
After Width: | Height: | Size: 2.1 KiB |
BIN
schasite/static/images/list-arrow.gif
Normal file
|
After Width: | Height: | Size: 115 B |
BIN
schasite/static/images/list-left.gif
Normal file
|
After Width: | Height: | Size: 313 B |
BIN
schasite/static/images/memberverification (1).gif
Normal file
|
After Width: | Height: | Size: 2.1 KiB |
BIN
schasite/static/images/memberverification.gif
Normal file
|
After Width: | Height: | Size: 2.1 KiB |
BIN
schasite/static/images/mid-body.gif
Normal file
|
After Width: | Height: | Size: 49 B |
BIN
schasite/static/images/nav-bar.gif
Normal file
|
After Width: | Height: | Size: 157 B |
BIN
schasite/static/images/news (1).gif
Normal file
|
After Width: | Height: | Size: 3.3 KiB |
BIN
schasite/static/images/news.gif
Normal file
|
After Width: | Height: | Size: 3.3 KiB |
BIN
schasite/static/images/rest-con.gif
Normal file
|
After Width: | Height: | Size: 176 B |
24
schasite/static/main.js
Normal file
@@ -0,0 +1,24 @@
|
||||
// static/main.js
|
||||
|
||||
console.log("Sanity Check");
|
||||
|
||||
fetch("/schasite/config/")
|
||||
.then((result) => {return result.json(); })
|
||||
.then((data) => {
|
||||
const stripe = Stripe(data.publicKey);
|
||||
|
||||
// Event Handler
|
||||
document.querySelector("#submitBtn").addEventListener("click", () => {
|
||||
// Get Checkout Session ID
|
||||
fetch("/schasite/create-checkout-session/")
|
||||
.then((result) => { return result.json(); })
|
||||
.then((data) => {
|
||||
console.log(data);
|
||||
// Redirect to Stripe Checkout
|
||||
return stripe.redirectToCheckout({sessionId: data.sessionId})
|
||||
})
|
||||
.then((res) => {
|
||||
console.log(res);
|
||||
});
|
||||
});
|
||||
});
|
||||
41
schasite/templates/schasite/about_us.html
Normal file
@@ -0,0 +1,41 @@
|
||||
{% extends 'schasite/base.html' %}
|
||||
{% load static %}
|
||||
|
||||
{% block pagetitle %}
|
||||
<title>Stonehedge Community Homeowners Association</title>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
|
||||
|
||||
<div class="mid-body">
|
||||
<h1>About <span>Stonehedge</span></h1>
|
||||
<div style="padding:10px 0 10px 0">
|
||||
<div class="clear">
|
||||
<p><strong>Education</strong></p>
|
||||
<p align="left">The Stonehedge Subdivision is proud to have excellent public and private schools. The public schools are part of <a href="http://www.cusd200.org/">Community Unit School District 200</a>. Stonehedge subdivision attends:</p>
|
||||
<p align="left">Whittier Elementary School, 218 W. Park Ave., Wheaton, IL 60189, (630) 682-2185<br />
|
||||
<a href="http://www.cusd200.org/Domain/1460">Whittier's Web site</a></p>
|
||||
<p align="left">Edison Middle School, 1125 S. Wheaton Ave., Wheaton, IL 60189, (630) 682-2050<br />
|
||||
<a href="http://www.cusd200.org/Domain/391">Edison's Web site</a></p>
|
||||
<p align="left">Wheaton Warrenville South High School, 1920 S. Wiesbrook Rd., Wheaton, IL 60189, (630) 784-7200<br />
|
||||
<a href="http://www.cusd200.org/Domain/140">WWSHS's Web site</a></p>
|
||||
<p align="left">There are many private schools in the area as well including Wheaton Christian Grammar School, Wheaton Montessori School, St. John Lutheran School, St. Michael Elementary School, St. Francis High School, Benet Academy and many more. Colleges include Devry, Benedictine, College of DuPage, Wheaton College, IIT, National Louis University, & North Central College.</p>
|
||||
<p><strong>History</strong></p>
|
||||
<p align="left">In 1977, Levitt Homes began building the Stonehedge Subdivision. In 1978, Levitt had financial problems and construction was halted for many months until local builders Joe Keim, Ed Keim and Faganel Builders took over the development of the Stonehedge subdivision in South Wheaton. Today these attractive residences are much in demand. The Orchard Cove subdivision was established in 1985 and development began in the Marywood subdivision in 1994. Both Orchard Cove & Marywood were built by Keim. </p>
|
||||
<p align="left">These subdivisions offer a variety of spacious, two-story Georgian, Tudor, Victorian and salt box style homes, mixed with a limited number of contemporaries, split levels and ranches.</p>
|
||||
<p align="left"><strong>Shopping</strong></p>
|
||||
<p align="left">Within walking distance and just east of the subdivisions, there are plenty of shopping centers including Danada East, Danada West, Towne Square & Rice Lake. You'll find supermarkets, post office, banks, restaurants, gas stations, craft stores, department stores, furniture stores, book stores, movie rental stores, dry cleaning facilities, ice cream stores, coffee shops and many other specialty stores.</p>
|
||||
<p align="left"><strong>Parks & Recreation</strong></p>
|
||||
<p align="left">The Stonehedge area is ideally suited for recreation. Seven Gables Park, at Brighton and Chatham, is maintained by the Wheaton Park District. It boasts a children's playground, a lake, soccer and baseball fields, picnic shelters, a 1.2 mile paved trail and a fitness course. In addition, there are several smaller parks also located directly within the subdivisions including Ridge Park & Brighton Park. Nearby is the state-of-the-art Rice Water Park and the Wheaton Park District Community Center, which includes a health and fitness center and indoor walking/jogging track and teen center. Arrowhead Golf Course, Herrick Lake, Blackwell Recreation Area, and the Illinois Prairie Path are just west on Butterfield Road.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="clear"></div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
{% endblock %}
|
||||
61
schasite/templates/schasite/base.html
Normal file
@@ -0,0 +1,61 @@
|
||||
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
{% load static %}
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
|
||||
{% block pagetitle %}
|
||||
{% endblock %}
|
||||
<title>Useful Links</title>
|
||||
<link href="{% static 'css/style.css' %}" rel="stylesheet" type="text/css" />
|
||||
<style type="text/css">
|
||||
|
||||
</style></head>
|
||||
|
||||
<body style="background-image: url('{% static "images/bricks.jpg"" %}');">
|
||||
<div id="header"></div>
|
||||
|
||||
<div class="nav-bar">
|
||||
<ul>
|
||||
<li><a href="{% url 'index' %}">HOME</a></li>
|
||||
<li><a href="{% url 'about_us' %}">ABOUT US</a></li>
|
||||
<li><a href="{% url 'calendar' %}">CALENDAR</a></li>
|
||||
<li><a href="{% url 'dues' %}">PAY DUES</a></li>
|
||||
<li><a href="{% url 'membership_form' %}">JOIN TODAY</a></li>
|
||||
<li><a href="{% url 'scha_board' %}">SCHA BOARD</a></li>
|
||||
<li><a href="{% url 'useful_links' %}">USEFUL LINKS</a></li>
|
||||
<li> </li>
|
||||
</ul>
|
||||
</div>
|
||||
{% block content %}
|
||||
{% endblock %}
|
||||
<div class="bt-cont">
|
||||
<div class="cont-rl">
|
||||
<img src="{% static 'images/memberverification.gif' %}" alt="" class="img-box" />
|
||||
<p>
|
||||
<span><a href="pdfs/Members/members2020.pdf">Are you an SCHA member?</a></span><br />
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="cont-rl">
|
||||
<img src="{% static 'images/facebook.gif' %}" alt="" class="img-box" />
|
||||
<p>
|
||||
<span><a href="https://www.facebook.com/groups/774502395977039/">Like us on facebook</a></span><br />
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="cont-rl">
|
||||
<img src="{% static 'images/news.gif' %}" alt="" class="img-box" />
|
||||
<p>
|
||||
<span><a href="{% url 'newsletters' %}">Digital <br />
|
||||
Newsletter</a></span> {# <span><a href="suggestion_box.html"></a></span><br /> #}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="clear"></div>
|
||||
</div>
|
||||
<div id="footer">© Stonehedge Community Homeowners Association 2010-<script>document.write( new Date().getFullYear() );</script>. All rights reserved
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
90
schasite/templates/schasite/calendar.html
Normal file
@@ -0,0 +1,90 @@
|
||||
{% extends 'schasite/base.html' %}
|
||||
{% load static %}
|
||||
|
||||
{% block pagetitle %}
|
||||
<title>Stonehedge Community Homeowners Association</title>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
|
||||
|
||||
<div class="mid-body">
|
||||
<h1>Calendar <span>of Events for 2024</span></h1>
|
||||
<div style="padding:10px 0 10px 0">
|
||||
<div class="clear">
|
||||
|
||||
<h2> Future Events</h2>
|
||||
{% if future_events %}
|
||||
{% for event in future_events %}
|
||||
<h3>{{ event.event_name }} </h3>
|
||||
{% if event.start_date == event.end_date %}
|
||||
<p>Date: {{ event.start_date }}</p>
|
||||
{% else %}
|
||||
<p>Date: {{ event.start_date }} - {{ event.end_date }}</p>
|
||||
{% endif %}
|
||||
<p>Location: {{ event.location_name }} - {{ event.calendareventaddressmodel }}</p>
|
||||
{% if event.coordinator_email %}
|
||||
<p>Coordinator: {{ event.coordinator_email }}</p>
|
||||
{% endif %}
|
||||
{% if event.event_url and event.event_link_name %}
|
||||
<p><a href="{{ event.url }}">{{ event.event_link_name }}</a></p>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% else %}
|
||||
<p> Stay tuned for more events!</p>
|
||||
{% endif %}
|
||||
|
||||
<h2>Past Events</h2>
|
||||
{% if past_events %}
|
||||
{% for event in past_events %}
|
||||
<h3>{{ event.event_name }} </h3>
|
||||
{% if event.start_date == event.end_date %}
|
||||
<p>Date: {{ event.start_date }}</p>
|
||||
{% else %}
|
||||
<p>Date: {{ event.start_date }} - {{ event.end_date }}</p>
|
||||
{% endif %}
|
||||
<p>Location: {{ event.location_name }} - {{ event.calendareventaddressmodel }}</p>
|
||||
{% if event.coordinator_email %}
|
||||
<p>Coordinator: {{ event.coordinator_email }}</p>
|
||||
{% endif %}
|
||||
{% if event.event_url and event.event_link_name %}
|
||||
<p><a href="{{ event.url }}">{{ event.event_link_name }}</a></p>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% else %}
|
||||
<p> Stay tuned for more events!</p>
|
||||
{% endif %}
|
||||
<!-- <p>Membership Drive: Ongoing</p>
|
||||
<p>Easter Egg Hunt: TBD at Brighton Park</p>
|
||||
|
||||
|
||||
<p>Spring Garage Sale: TBD</p>
|
||||
|
||||
|
||||
<p>Ice Cream Social: TBD at Brighton Park<p>
|
||||
|
||||
<p>Stonehedge Sandbagger Scramble: TBD at Arrowhead Golf Course
|
||||
|
||||
|
||||
<p>Fall Garage Sale: TBD</p>
|
||||
|
||||
|
||||
<p>1st Annual Witches and Warlocks Halloween Ride: TBD</p>
|
||||
|
||||
|
||||
<p>Annual Meeting: November TBD </p>
|
||||
|
||||
<p>Santa Visits: December TBD</p>
|
||||
|
||||
<p>Holiday Decorating Contest: December TBD</p> -->
|
||||
|
||||
<p><b>Event Feedack Coming Soon!</b></p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="clear"></div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
{% endblock %}
|
||||
23
schasite/templates/schasite/dues.html
Normal file
@@ -0,0 +1,23 @@
|
||||
{% extends 'schasite/base.html' %}
|
||||
{% load static %}
|
||||
|
||||
{% block pagetitle %}
|
||||
<title>Stonehedge Community Homeowners Association</title>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<script src="https://js.stripe.com/v3/"></script>
|
||||
<script src="{% static 'main.js' %}"></script>
|
||||
|
||||
|
||||
<div class="mid-body">
|
||||
<h1>Dues <span>Coming soon!</span></h1>
|
||||
<button class="button is-primary" id="submitBtn">Pay Dues</button>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
{% endblock %}
|
||||
17
schasite/templates/schasite/dues_cancelled.html
Normal file
@@ -0,0 +1,17 @@
|
||||
{% extends 'schasite/base.html' %}
|
||||
{% load static %}
|
||||
|
||||
{% block pagetitle %}
|
||||
<title>Stonehedge Community Homeowners Association</title>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
|
||||
|
||||
<div class="mid-body">
|
||||
<h1>Your payment cancelled.</h1>
|
||||
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
||||
17
schasite/templates/schasite/dues_success.html
Normal file
@@ -0,0 +1,17 @@
|
||||
{% extends 'schasite/base.html' %}
|
||||
{% load static %}
|
||||
|
||||
{% block pagetitle %}
|
||||
<title>Stonehedge Community Homeowners Association</title>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
|
||||
|
||||
<div class="mid-body">
|
||||
<h1>Your payment succeeded.</h1>
|
||||
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
||||
79
schasite/templates/schasite/index.html
Normal file
@@ -0,0 +1,79 @@
|
||||
{% extends 'schasite/base.html' %}
|
||||
{% load static %}
|
||||
|
||||
{% block pagetitle %}
|
||||
<title>Stonehedge Community Homeowners Association</title>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
|
||||
|
||||
<div class="mid-body">
|
||||
<h1>Stonehedge <span>Community Homeowners Association</span></h1>
|
||||
<div style="padding:10px 0 10px 0">
|
||||
|
||||
|
||||
<div>Thank you for visiting our web site. This is the official Web site for the Stonehedge Community Homeowners Association serving Stonehedge, Golden Pond and Marywood of Wheaton, Illinois. We are located west of Naperville Road and North of Butterfield Road. <br />
|
||||
<br />
|
||||
<br />
|
||||
<div class="clear"></div>
|
||||
</div>
|
||||
<div class="clear"></div>
|
||||
<div class="clear"></div>
|
||||
<div class="aboutcolumnzone">
|
||||
|
||||
|
||||
<div class="clear"></div>
|
||||
<div class="aboutcolumn1">
|
||||
<div>
|
||||
|
||||
<h5>Spring Garage Sale</h5>
|
||||
<img src="{% static 'images/garage_sale.gif' %}" alt="" class="abouticon" />Ready to do some spring cleaning? Check back for the SCHA Spring Garage Sale dates and registration form.
|
||||
|
||||
<div class="insidereadmore"><a href="{% url 'calendar' %}">More Information</a></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="aboutcolumn2">
|
||||
<div>
|
||||
|
||||
<h5>Easter Egg Hunt</h5>
|
||||
<img src="{% static 'images/easter.gif' %}" alt="" class="abouticon" />Bring the kids for our annual Easter Egg Hunt. More details coming soon.
|
||||
|
||||
<div class="insidereadmore"><a href="{% url 'calendar' %}" >More Information</a></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="clear"></div>
|
||||
<div class="aboutcolumn1">
|
||||
<div>
|
||||
|
||||
<h5>Join Today</h5>
|
||||
<img src="{% static 'images/jointoday.gif' %}" alt="" class="abouticon" />Become a Stonehedge member and your membership dues help to fund our family friendly, fun activities and to maintain our beautiful entry drives.
|
||||
<div class="insidereadmore"><a href="{% url 'membership_form' %}">More Information</a></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="aboutcolumn2">
|
||||
<div>
|
||||
|
||||
<h5>Drive Safely!</h5>
|
||||
<img src="{% static 'images/25.gif' %}" alt="" class="abouticon" />This is a friendly reminder that the speed limit in the subdivision is 25. Drive safely and watch for children and pets.
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="clear"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<!--<h5>Cromwell Connector Trail</h5>
|
||||
<img src="images/tree.gif" alt="" class="abouticon" />Learn about new and upcoming DuPage County Forest Preserve projects including the Cromwell Connector Trail.
|
||||
<div class="insidereadmore"><a href="http://schawheaton.com/dupageforestpreserve.html">More Information</a></div>
|
||||
</div>
|
||||
</div>-->
|
||||
|
||||
{% endblock %}
|
||||
97
schasite/templates/schasite/membership_form.html
Normal file
@@ -0,0 +1,97 @@
|
||||
{% extends 'schasite/base.html' %}
|
||||
{% load static %}
|
||||
|
||||
{% block pagetitle %}
|
||||
<title>Stonehedge Community Homeowners Association</title>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<div class="mid-body">
|
||||
<h1>Membership <span>Form for 2024</span></h1>
|
||||
<div style="padding:10px 0 10px 0">
|
||||
<div class="clear">
|
||||
<form method="POST" action='{% url "membership_form" %}'>
|
||||
{% csrf_token %}
|
||||
<div class="aboutcolumnzone">
|
||||
<div class="aboutcolumn1">
|
||||
<h5>Person #1</h5>
|
||||
{% for field in peopleForm1 %}
|
||||
<div class="fieldWrapper">
|
||||
{{ field.errors }}
|
||||
{{ field.label_tag }} : {{ field }}
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
<div class="aboutcolumn2">
|
||||
<h5>Person #2</h5>
|
||||
{% for field in peopleForm2 %}
|
||||
<div class="fieldWrapper">
|
||||
{{ field.errors }}
|
||||
{{ field.label_tag }} : {{ field }}
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="aboutcolumnzone">
|
||||
<div class="aboutcolumn1">
|
||||
<h5>Address</h5>
|
||||
{% for field in addressForm %}
|
||||
<div class="fieldWrapper">
|
||||
{{ field.errors }}
|
||||
{{ field.label_tag }} : {{ field }}
|
||||
</div>
|
||||
{% endfor %}
|
||||
<h5>Children</h5>
|
||||
{% for field in membershipForm %}
|
||||
<div class="fieldWrapper">
|
||||
{{ field.errors }}
|
||||
{{ field.label_tag }} : {{ field }}
|
||||
</div>
|
||||
<p>Please add the names as a comma seperated list. i.e. Bob, Cindy</p>
|
||||
{% endfor %}
|
||||
<h5>Services Information</h5>
|
||||
{% for field in servicesForm %}
|
||||
<div class="fieldWrapper">
|
||||
{{ field.errors }}
|
||||
{{ field }} : {{ field.label_tag }}
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
<div class="aboutcolumn2">
|
||||
<h5>Committee Information</h5>
|
||||
{% for field in committeeForm %}
|
||||
<div class="fieldWrapper">
|
||||
{{ field.errors }}
|
||||
{{ field }} : {{ field.label_tag }}
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="clear"></div>
|
||||
{% if err_msg %}
|
||||
<div>
|
||||
<p>{{ err_msg }}</p>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if captchaForm %}
|
||||
{{ captchaForm }}
|
||||
{% endif %}
|
||||
|
||||
<button type=""button" value="submit">Submit</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<p><strong>Please note dues will be $30 for 2024.</strong></p>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="clear"></div>
|
||||
|
||||
|
||||
|
||||
{% endblock %}
|
||||
86
schasite/templates/schasite/newsletters.html
Normal file
@@ -0,0 +1,86 @@
|
||||
{% extends 'schasite/base.html' %}
|
||||
{% load static %}
|
||||
|
||||
{% block pagetitle %}
|
||||
<title>Stonehedge Community Homeowners Association</title>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
|
||||
|
||||
<div class="mid-body">
|
||||
|
||||
<h1>Newsletters</h1>
|
||||
|
||||
<div style="padding:10px 0 10px 0">
|
||||
|
||||
<div class="clear">
|
||||
<p><a href="pdfs/Newsletters/MarchApril2020.pdf">March/April 2020</a> (pdf)</p>
|
||||
<p><a href="pdfs/Newsletters/Jan2020.pdf">January 2020</a> (pdf)</p>
|
||||
<p><a href="pdfs/Newsletters/NovDec2019.pdf">November/December 2019</a> (pdf)</p>
|
||||
<p><a href="pdfs/Newsletters/Oct2019.pdf">October 2019</a> (pdf)</p>
|
||||
<p><a href="pdfs/Newsletters/Sept2019.pdf">September 2019</a> (pdf)</p>
|
||||
<p><a href="pdfs/Newsletters/Aug19.pdf">August 2019</a> (pdf)</p>
|
||||
<p><a href="pdfs/Newsletters/July2019.pdf">July 2019</a> (pdf)</p>
|
||||
<p><a href="pdfs/Newsletters/NovDec2016News.pdf">November/December 2016</a> (pdf)</p>
|
||||
<p><a href="pdfs/Newsletters/SeptOct2016v2.pdf">September/October 2016</a> (pdf)</p>
|
||||
<p><a href="pdfs/Newsletters/JulAug2016.pdf">July/August 2016</a> (pdf) Inserts: <a href="pdfs/IceCream/icecreamsmash2016.pdf">Ice Cream Smash</a> & <a href="pdfs/GolfOuting/SCHAGolfOuting2016.pdf">Sandbagger Scramble</a></p>
|
||||
<p><a href="pdfs/Newsletters/MayJune2016.pdf">May/June 2016</a> (pdf) </p>
|
||||
<p><a href="pdfs/Newsletters/MarApr16.pdf">March/April 2016</a> (pdf) Inserts: <a href="pdfs/MembershipForms/2016MembershipForm.pdf">2016 Membership Form</a> & <a href="pdfs/BlockCaptains/2016.pdf">Block Captain Thank You</a></p>
|
||||
<p><a href="pdfs/Newsletters/JanFeb2016.pdf">January/February 2016</a> (pdf) Inserts: <a href="pdfs/MembershipForms/2016MembershipForm.pdf">2016 Membership Form</a> & <a href="pdfs/HolidayDoors2015.pdf">Holiday Doors</a></p>
|
||||
<p><a href="pdfs/Newsletters/NovDec2015.pdf">November/December 2015</a> (pdf) </p>
|
||||
<p><a href="pdfs/Newsletters/SeptOct2015.pdf">September/October 2015</a> (pdf) Inserts: <a href="pdfs/garagesale/Fall15.pdf">Garage Sale Flyer</a></p>
|
||||
<p><a href="pdfs/Newsletters/JulyAug2015.pdf">July/August 2015</a> (pdf) Inserts: <a href="pdfs/garagesale/fall2015.pdf">Garage Sale Flyer</a> & <a href="pdfs/gardenclub/gardenwalk0715.pdf">Garden Walk</a></p>
|
||||
<p><a href="pdfs/Newsletters/MayJune2015.pdf">May/June 2015</a> (pdf)</p>
|
||||
<p><a href="pdfs/Newsletters/MarApr2015.pdf">March/April 2015</a> (pdf) Inserts: <a href="pdfs/garagesale/spring15.pdf">Garage Sale Flyer</a> & <a href="pdfs/GolfOuting/SCHAGolfOuting2015.pdf">Golf Outing Flyer</a></p>
|
||||
<p><a href="pdfs/Newsletters/JanFeb2015.pdf">January/February 2015</a> (pdf) </p>
|
||||
<p><a href="pdfs/MembershipForms/2015.pdf">January 2015 - Annual Membership Form</a> (pdf) </p>
|
||||
<p><a href="pdfs/Newsletters/NovDec2014.pdf">November/December 2014</a> (pdf) </p>
|
||||
<p><a href="pdfs/Newsletters/SeptOct2014.pdf">September/October 2014</a> (pdf) Inserts: <a href="pdfs/garagesale/Fall2014.pdf">garage sale flyer</a></p>
|
||||
<p><a href="pdfs/Newsletters/JulAug2014.pdf">July/August 2014</a> (pdf) </p>
|
||||
<p><a href="pdfs/Newsletters/MayJune2014.pdf">May/June 2014</a> (pdf) Inserts: <a href="pdfs/MembershipForms/membership.pdf">membership form</a> & <a href="pdfs/garagesale/garage_sale_spring2014 .pdf">garage sale flyer</a></p>
|
||||
<p><a href="pdfs/Newsletters/MarApr2014.pdf">March/April 2014</a> (pdf)</p>
|
||||
<p><a href="pdfs/Newsletters/JanFeb2014.pdf">Jan/Feb 2014</a> (pdf)</p>
|
||||
<p><a href="pdfs/Newsletters/NovDec2013.pdf">November/December 2013</a> (pdf)</p>
|
||||
<p><a href="pdfs/Newsletters/SeptOct2013.pdf">September/October 2013</a> (pdf)</p>
|
||||
|
||||
<p><a href="pdfs/Newsletters/JulAug2013.pdf">July/August 2013</a> (pdf)</p>
|
||||
|
||||
<p><a href="pdfs/Newsletters/MayJune2013.pdf">May/June 2013</a> (pdf)</p>
|
||||
|
||||
<p><a href="pdfs/Newsletters/MarApr2013.pdf">March/April 2013</a> (pdf)</p>
|
||||
|
||||
<p><a href="pdfs/Newsletters/JanFeb2013.pdf">January/February 2013</a> (pdf) </p>
|
||||
<h1><strong><em>Interested in advertising in our newsletter?</em></strong></h1>
|
||||
|
||||
<p><strong>Advertising Rates: </strong><br />
|
||||
|
||||
1/4 page: $70<br />
|
||||
1/2 page: $90 <br />
|
||||
|
||||
Full page: $175</p>
|
||||
<p><strong>Issue Deadlines:</strong><br />
|
||||
|
||||
July/August - July 3<br />
|
||||
|
||||
September/October - September 1<br />
|
||||
|
||||
November/December - November 1 <br />
|
||||
|
||||
</p>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="clear"></div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
{% endblock %}
|
||||
77
schasite/templates/schasite/scha_board.html
Normal file
@@ -0,0 +1,77 @@
|
||||
{% extends 'schasite/base.html' %}
|
||||
{% load static %}
|
||||
|
||||
{% block pagetitle %}
|
||||
<title>Stonehedge Community Homeowners Association</title>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
|
||||
|
||||
<div class="mid-body">
|
||||
<h1>SCHA <span>Board Members for 2022</span></h1>
|
||||
<div style="padding:10px 0 10px 0">
|
||||
<table width="565" border="1" cellspacing="0" cellpadding="1">
|
||||
<tr>
|
||||
<td width="167"><p>Monica Dhillon</p></td>
|
||||
<td width="196"><p>President</p></td>
|
||||
<td width="202"><p><a href="mailto:moni.dhill@gmail.com">moni.dhill@gmail.com</a></p></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><p>Teresa Westfall</p></td>
|
||||
<td><p>1st Vice President</p></td>
|
||||
<td width="202"><p><a href="mailto:teresa.westfall299@gmail.com">teresa.westfall299@gmail.com</a></p></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><p>Tom Hatting</p></td>
|
||||
<td><p>2nd Vice President</p></td>
|
||||
<td><p><a href="mailto:tmhatting@comcast.net">tmhatting@comcast.net</a></p></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><p>Chris Cozart</p></td>
|
||||
<td><p>Treasurer</p></td>
|
||||
<td><p><a href="mailto:cdcozart@aol.com">cdcozart@aol.com</a></p></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><p>Anna Malik</p></td>
|
||||
<td><p>Secretary</p></td>
|
||||
<td><p><a href="mailto:Malik.anusha@gmail.com">Malik.anusha@gmail.com</a></p></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><p>Jill Feitl</p></td>
|
||||
<td><p>Web site</p></td>
|
||||
<td><p><a href="mailto:jfeitl@hotmail.com">jfeitl@hotmail.com</a></p></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><p>Wendy Peck</p></td>
|
||||
<td><p>Membership</p></td>
|
||||
<td><p><a href="wlpeck116@gmail.com">wlpeck116@gmail.com</a></p></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><p>Melissa Gonski<br>
|
||||
Mike Joyce</p></td>
|
||||
<td><p>Directory</p></td>
|
||||
<td><p><a href="mailto:melissagonski@gmail.com">melissagonski@gmail.com</a><br>
|
||||
<a href="mailto:mike.joyce@bairdwarner.com">mike.joyce@bairdwarner.com</a>
|
||||
</p></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><p>Pat Hanika</p></td>
|
||||
<td><p>Facebook</p></td>
|
||||
<td><p><a href="mailto:pathanika@gmail.com">pathanika@gmail.com</a></p></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><p>Stephanie Bakula</p></td>
|
||||
<td><p>Eblasts</p></td>
|
||||
<td><p><a href="mailto:sabakula@gmail.com">sabakula@gmail.com</a></p></td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
{% endblock %}
|
||||
29
schasite/templates/schasite/useful_links.html
Normal file
@@ -0,0 +1,29 @@
|
||||
{% extends 'schasite/base.html' %}
|
||||
{% load static %}
|
||||
|
||||
{% block pagetitle %}
|
||||
<title>Useful Links</title>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<div class="mid-body">
|
||||
<h1>Useful <span>Links</span></h1>
|
||||
<div style="padding:10px 0 10px 0">
|
||||
<div class="clear">
|
||||
|
||||
{% if links %}
|
||||
{% for link in links %}
|
||||
<p><a href="{{ link.url }}">{{ link.name }}</a></p>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="clear"></div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
{% endblock %}
|
||||
3
schasite/tests.py
Normal file
@@ -0,0 +1,3 @@
|
||||
from django.test import TestCase
|
||||
|
||||
# Create your tests here.
|
||||
17
schasite/urls.py
Normal file
@@ -0,0 +1,17 @@
|
||||
from django.urls import path
|
||||
|
||||
from . import views
|
||||
|
||||
urlpatterns = [
|
||||
path("", views.index, name="index"),
|
||||
path("useful_links", views.useful_links, name="useful_links"),
|
||||
path("about_us", views.about_us, name="about_us"),
|
||||
path("calendar", views.calendar, name="calendar"),
|
||||
path("newsletters", views.newsletters, name="newsletters"),
|
||||
path("dues", views.dues, name="dues"),
|
||||
path("membership_form", views.membership_form, name="membership_form"),
|
||||
path("scha_board", views.scha_board, name="scha_board"),
|
||||
# stripe specific urls below
|
||||
path('config/', views.stripe_config),
|
||||
path('create-checkout-session/', views.create_checkout_session),
|
||||
]
|
||||
199
schasite/views.py
Normal file
@@ -0,0 +1,199 @@
|
||||
from django.shortcuts import render, redirect
|
||||
from .models import UsefulLinks, CalendarEvent, MembershipPerson, Payments
|
||||
from .forms import ChildrenForm, AddressForm, PeopleForm, CommitteeForm, ServicesForm#, CaptchaForm
|
||||
from django.db import transaction, IntegrityError
|
||||
# Stripe required imports
|
||||
from django.conf import settings # new
|
||||
from django.http.response import JsonResponse, HttpResponse
|
||||
from django.views.decorators.csrf import csrf_exempt # new
|
||||
import stripe
|
||||
|
||||
"""
|
||||
Strip Stuff
|
||||
Tutorial: https://testdriven.io/blog/django-stripe-tutorial/
|
||||
"""
|
||||
def dues(request):
|
||||
return render(request, "schasite/dues.html", {})
|
||||
|
||||
@csrf_exempt
|
||||
def stripe_config(request):
|
||||
if request.method == 'GET':
|
||||
stripe_config = {'publicKey': settings.STRIPE_PUBLISHABLE_KEY}
|
||||
return JsonResponse(stripe_config, safe=False)
|
||||
|
||||
@csrf_exempt
|
||||
def create_checkout_session(request):
|
||||
if request.method == 'GET':
|
||||
domain_url = "http://localhost:8000/"
|
||||
stripe.api_key = settings.STRIPE_SECRET_KEY
|
||||
try:
|
||||
checkout_session = stripe.checkout.Session.create(
|
||||
success_url = domain_url+'success?session_id={CHECKOUT_SESSION_ID}',
|
||||
cancel_url = domain_url+'cancelled/',
|
||||
payment_method_types=['card'],
|
||||
mode="payment",
|
||||
line_items = [{
|
||||
# 'name':'SCHA Dues',
|
||||
'quantity': 1,
|
||||
# 'currency': 'usd',
|
||||
'price': 'price_1OxZLfDV0RPXOyxG5ipjhUXk',
|
||||
}]
|
||||
)
|
||||
return JsonResponse({'sessionId': checkout_session['id']})
|
||||
except Exception as e:
|
||||
return JsonResponse({'error': str(e)})
|
||||
|
||||
def stripe_success(request):
|
||||
return render(request, "schasite/dues_success.html", {})
|
||||
|
||||
def stripe_cancelled(request):
|
||||
return render(request, "schasite/dues_cancelled.html", {})
|
||||
|
||||
@csrf_exempt
|
||||
def stripe_webhook(request):
|
||||
stripe.api_key = settings.STRIPE_SECRET_KEY
|
||||
endpoint_secret = settings.STRIPE_ENDPOINT_SECRET
|
||||
payload = request.body
|
||||
sig_header = request.META['HTTP_STRIPE_SIGNATURE']
|
||||
event = None
|
||||
|
||||
try:
|
||||
event = stripe.Webhook.construct_event(
|
||||
payload, sig_header, endpoint_secret
|
||||
)
|
||||
except ValueError as e:
|
||||
# Invalid payload
|
||||
return HttpResponse(status=400)
|
||||
except stripe.error.SignatureVerificationError as e:
|
||||
# Invalid signature
|
||||
return HttpResponse(status=400)
|
||||
|
||||
# Handle the checkout.session.completed event
|
||||
if event['type'] == 'checkout.session.completed':
|
||||
email = None
|
||||
try:
|
||||
email = event['data']['object']['customer_details']['email']
|
||||
except:
|
||||
pass
|
||||
person = MembershipPerson.objects.filter(email=email).first() # just take the first
|
||||
|
||||
payment = Payments.objects.create(
|
||||
email=email,
|
||||
person = person
|
||||
)
|
||||
# try to link to a member
|
||||
payment.save()
|
||||
# TODO: run some custom code here
|
||||
|
||||
return HttpResponse(status=200)
|
||||
|
||||
"""
|
||||
Django Stuff
|
||||
"""
|
||||
def useful_links(request):
|
||||
useful_links = UsefulLinks.objects.all()
|
||||
return render(request, "schasite/useful_links.html", {"links": useful_links})
|
||||
|
||||
def index(request):
|
||||
return render(request, "schasite/index.html", {})
|
||||
|
||||
def about_us(request):
|
||||
return render(request, "schasite/about_us.html", {})
|
||||
|
||||
def calendar(request):
|
||||
all_events = CalendarEvent.objects.all()
|
||||
future_events = [event if event.future_event() else None for event in all_events]
|
||||
past_events = [event if event.past_event() else None for event in all_events]
|
||||
# remove none for each list
|
||||
sanitized_future_events = [i for i in future_events if i is not None]
|
||||
sanitized_past_events = [i for i in past_events if i is not None]
|
||||
return render(request, "schasite/calendar.html", {'future_events': sanitized_future_events,
|
||||
'past_events': sanitized_past_events})
|
||||
|
||||
def newsletters(request):
|
||||
return render(request, "schasite/newsletters.html", {})
|
||||
|
||||
def membership_form(request):
|
||||
def sanitize_phone_number(data):
|
||||
if len(data) > 0:
|
||||
data = data.replace('-','')
|
||||
if not data.startswith('+1'):
|
||||
data = '+1' + data
|
||||
|
||||
return data
|
||||
if request.method == "POST":
|
||||
# before we pass in the data we want to sanitize the phone numbers
|
||||
post_data = request.POST.copy()
|
||||
post_data.update({'person1-phone_number':sanitize_phone_number(post_data['person1-phone_number'])})
|
||||
post_data.update({'person2-phone_number':sanitize_phone_number(post_data['person2-phone_number'])})
|
||||
membershipForm = ChildrenForm(post_data)
|
||||
addressForm = AddressForm(post_data)
|
||||
peopleForm1 = PeopleForm(post_data, prefix='person1')
|
||||
peopleForm2 = PeopleForm(post_data, prefix='person2')
|
||||
servicesForm = ServicesForm(post_data)
|
||||
committeeForm= CommitteeForm(post_data)
|
||||
# captchaForm = CaptchaForm(post_data)
|
||||
|
||||
|
||||
if membershipForm.is_valid() and addressForm.is_valid() and committeeForm.is_valid() and (peopleForm1.is_valid() or peopleForm2.is_valid()) and servicesForm.is_valid(): # and captchaForm.is_valid():
|
||||
with transaction.atomic():
|
||||
membershipForm = ChildrenForm({**post_data})
|
||||
membership = membershipForm.save(commit=False)
|
||||
membership.save()
|
||||
|
||||
if peopleForm1.is_valid():
|
||||
people1_obj = peopleForm1.save(commit=False)
|
||||
people1_obj.membership = membership
|
||||
people1_obj.save()
|
||||
|
||||
if peopleForm2.is_valid():
|
||||
people2_obj = peopleForm2.save(commit=False)
|
||||
people2_obj.membership = membership
|
||||
people2_obj.save()
|
||||
|
||||
committee_obj = committeeForm.save(commit=False)
|
||||
committee_obj.membership = membership
|
||||
committee_obj.save()
|
||||
|
||||
services_obj = servicesForm.save(commit=False)
|
||||
services_obj.membership = membership
|
||||
services_obj.save()
|
||||
|
||||
address_obj = addressForm.save(commit=False)
|
||||
address_obj.membership = membership
|
||||
address_obj.save()
|
||||
|
||||
return redirect('index')
|
||||
|
||||
|
||||
else:
|
||||
return render(request,
|
||||
"schasite/membership_form.html",
|
||||
{
|
||||
'membershipForm': ChildrenForm,
|
||||
'peopleForm1': peopleForm1,
|
||||
'peopleForm2': peopleForm2,
|
||||
'addressForm': addressForm,
|
||||
'committeeForm' : committeeForm,
|
||||
'servicesForm': servicesForm,
|
||||
# 'captchaForm': captchaForm,
|
||||
} )
|
||||
else:
|
||||
return render(request,
|
||||
"schasite/membership_form.html",
|
||||
{'membershipForm': ChildrenForm(),
|
||||
'peopleForm1': PeopleForm(prefix='person1'),
|
||||
'peopleForm2': PeopleForm(prefix='person2'),
|
||||
'committeeForm' : CommitteeForm(),
|
||||
'servicesForm': ServicesForm(),
|
||||
# 'captchaForm': CaptchaForm(),
|
||||
"addressForm": AddressForm(
|
||||
initial={
|
||||
"city": "Wheaton",
|
||||
"state": "IL",
|
||||
"zip_code": 60189,
|
||||
}
|
||||
)})
|
||||
|
||||
def scha_board(request):
|
||||
return render(request, "schasite/scha_board.html", {})
|
||||