diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 4a60eff..2a82bf3 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -1,9 +1,11 @@ { "name": "DSA - ActionKit Templates", "image": "mcr.microsoft.com/devcontainers/python:1-3.11-bullseye", - "postCreateCommand": "pip install -e .", + "postAttachCommand": "pip install -e .", "containerEnv": { - "DJANGO_SETTINGS_MODULE": "dsa_actionkit.settings" + "DJANGO_SETTINGS_MODULE": "dsa_actionkit.settings", + "ROOT_URLCONF": "dsa_actionkit.urls", + "DJANGO_SECRET_KEY": "solidarityforever" }, "customizations": { "vscode": { @@ -11,7 +13,13 @@ "ms-python.python", "tamasfe.even-better-toml", "samuelcolvin.jinjahtml", - "batisteo.vscode-django" + "batisteo.vscode-django", + "charliermarsh.ruff", + "eamodio.gitlens", + "GitHub.vscode-github-actions", + "tamasfe.even-better-toml", + "esbenp.prettier-vscode", + "redhat.vscode-yaml" ] }, "settings": { @@ -23,5 +31,23 @@ "editor.defaultFormatter": "samuelcolvin.jinjahtml", "editor.formatOnSave": true }, + "python.terminal.activateEnvInCurrentTerminal": true, + "[python]": { + "editor.codeActionsOnSave": { + "source.fixAll.ruff": true, + "source.organizeImports.ruff": true + }, + "editor.defaultFormatter": "charliermarsh.ruff" + }, + "python.testing.cwd": "tests", + "python.testing.unittestEnabled": false, + "python.testing.pytestEnabled": true, + "editor.formatOnSave": true, + "editor.formatOnPaste": true, + "editor.stickyScroll.enabled": true, + "dbt.enableNewLineagePanel": true, + "files.insertFinalNewline": true, + "terminal.integrated.environmentChangesIndicator": "on" + } } -} \ No newline at end of file +} diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml new file mode 100644 index 0000000..41cdc16 --- /dev/null +++ b/.github/workflows/ci.yaml @@ -0,0 +1,23 @@ +name: CI + + +on: + push: + branches: + - main + pull_request: + branches: + - main + + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Install packages + run: | + pip install . + - name: Run Tests + run: | + pytest diff --git a/.gitignore b/.gitignore index 253ba83..4bbb8c1 100644 --- a/.gitignore +++ b/.gitignore @@ -16,4 +16,5 @@ site.css.map build .venv dist -*.egg-info \ No newline at end of file +*.egg-info +db.sqlite \ No newline at end of file diff --git a/dsa_actionkit/aktemplates.py b/dsa_actionkit/aktemplates.py index 8a602dc..9f8f5f6 100755 --- a/dsa_actionkit/aktemplates.py +++ b/dsa_actionkit/aktemplates.py @@ -1,6 +1,7 @@ #!/usr/bin/env python import os import sys + #STATIC_FALLBACK="/static/js/fallback_local" PYTHONPATH=./djanger django-admin runserver --settings=settings diff --git a/dsa_actionkit/contexts/account_contexts.py b/dsa_actionkit/contexts/account_contexts.py index 10805a2..0afc49f 100644 --- a/dsa_actionkit/contexts/account_contexts.py +++ b/dsa_actionkit/contexts/account_contexts.py @@ -1,318 +1,320 @@ import datetime + from . import lib + class subscriptions(list): list_ids = [1, 3, 7] contexts = { - 'user_view.html': { - 'filename': 'user_view.html', - 'page': { - 'title': 'User self serve', - 'name': 'user view', + "user_view.html": { + "filename": "user_view.html", + "page": { + "title": "User self serve", + "name": "user view", }, }, - 'signup.html': { - 'filename': 'signup.html', - 'page': { - 'title': 'Signup!', - 'name': 'signup', + "signup.html": { + "filename": "signup.html", + "page": { + "title": "Signup!", + "name": "signup", "custom_fields": { "entity": "pac", - "layout_options": "lost_pages_redesign" - } + "layout_options": "lost_pages_redesign", + }, }, - 'form': { - 'introduction_text': 'Signup now!', - 'user_fields': { - 'first_name': 'Ann' - } + "form": { + "introduction_text": "Signup now!", + "user_fields": { + "first_name": "Ann", + }, }, - 'user_fields': [ - {'field_name': 'name', - 'label_text': 'Name', - 'input_tag': '', + "user_fields": [ + {"field_name": "name", + "label_text": "Name", + "input_tag": '', }, - {'field_name': 'email', - 'label_text': 'Email Address', - 'input_tag': '', + {"field_name": "email", + "label_text": "Email Address", + "input_tag": '', }, - {'field_name': 'address1', - 'label_text': 'Street Address', - 'input_tag': '', + {"field_name": "address1", + "label_text": "Street Address", + "input_tag": '', }, - {'field_name': 'zip', - 'label_text': 'ZIP Code', - 'input_tag': '', + {"field_name": "zip", + "label_text": "ZIP Code", + "input_tag": '', }, - {'field_name': 'phone', - 'label_text': 'Phone', - 'input_tag': '', + {"field_name": "phone", + "label_text": "Phone", + "input_tag": '', }, ], }, - 'signup.smssubscribe': { - 'filename': 'signup.html', - 'page': { - 'title': 'Signup! sms-opt-out', - 'name': 'signup', + "signup.smssubscribe": { + "filename": "signup.html", + "page": { + "title": "Signup! sms-opt-out", + "name": "signup", "custom_fields": { "entity": "pac", - "phone_mobile": "opt-out" - } + "phone_mobile": "opt-out", + }, }, - 'form': { - 'introduction_text': 'Signup now!', - 'user_fields': { - 'first_name': 'Ann' - } + "form": { + "introduction_text": "Signup now!", + "user_fields": { + "first_name": "Ann", + }, }, - 'user_fields': [ - {'field_name': 'name', - 'label_text': 'Name', - 'input_tag': '', + "user_fields": [ + {"field_name": "name", + "label_text": "Name", + "input_tag": '', }, - {'field_name': 'email', - 'label_text': 'Email Address', - 'input_tag': '', + {"field_name": "email", + "label_text": "Email Address", + "input_tag": '', }, - {'field_name': 'address1', - 'label_text': 'Street Address', - 'input_tag': '', + {"field_name": "address1", + "label_text": "Street Address", + "input_tag": '', }, - {'field_name': 'zip', - 'label_text': 'ZIP Code', - 'input_tag': '', + {"field_name": "zip", + "label_text": "ZIP Code", + "input_tag": '', }, - {'field_name': 'phone', - 'label_text': 'Phone', - 'input_tag': '', + {"field_name": "phone", + "label_text": "Phone", + "input_tag": '', }, ], }, - 'user_update.html': lib.userform({ - 'filename': 'user_update.html', - 'page': { - 'title': 'Update Your Information', - 'name': 'user-update', + "user_update.html": lib.userform({ + "filename": "user_update.html", + "page": { + "title": "Update Your Information", + "name": "user-update", "custom_fields": { - "entity": "pac" + "entity": "pac", }, "followup": { - "share_title": "" - } + "share_title": "", + }, }, - 'user': lib.user({ + "user": lib.user({ "id": "7338", "name": "George Costanza", "phone": "515-555-0199", }), }, { # form - 'introduction_text': 'Please update your information below', - 'user_fields': [ - {'field_name': 'email', - 'label_text': 'Email Address', - 'input_tag': '', + "introduction_text": "Please update your information below", + "user_fields": [ + {"field_name": "email", + "label_text": "Email Address", + "input_tag": '', }, - {'field_name': 'prefix', - 'label_text': 'Prefix', - 'input_tag': '', + {"field_name": "prefix", + "label_text": "Prefix", + "input_tag": '', }, - {'field_name': 'first_name', - 'label_text': 'First name', - 'input_tag': '', + {"field_name": "first_name", + "label_text": "First name", + "input_tag": '', }, - {'field_name': 'middle_name', - 'label_text': 'Middle name', - 'input_tag': '', + {"field_name": "middle_name", + "label_text": "Middle name", + "input_tag": '', }, - {'field_name': 'last_name', - 'label_text': 'Last name', - 'input_tag': '', + {"field_name": "last_name", + "label_text": "Last name", + "input_tag": '', }, - {'field_name': 'suffix', - 'label_text': 'Suffix', - 'input_tag': '', + {"field_name": "suffix", + "label_text": "Suffix", + "input_tag": '', }, - {'field_name': 'country', - 'label_text': 'Country', - 'input_tag': lib.countries(), + {"field_name": "country", + "label_text": "Country", + "input_tag": lib.countries(), }, - {'field_name': 'address1', - 'label_text': 'Street Address', - 'input_tag': '', + {"field_name": "address1", + "label_text": "Street Address", + "input_tag": '', }, - {'field_name': 'address2', - 'label_text': 'Street Address', - 'input_tag': '', + {"field_name": "address2", + "label_text": "Street Address", + "input_tag": '', }, - {'field_name': 'city', - 'label_text': 'City', - 'input_tag': '', + {"field_name": "city", + "label_text": "City", + "input_tag": '', }, - {'field_name': 'state', - 'label_text': 'State', - 'input_tag': lib.states(), + {"field_name": "state", + "label_text": "State", + "input_tag": lib.states(), }, - {'field_name': 'zip', - 'label_text': 'Zip', - 'input_tag': '', + {"field_name": "zip", + "label_text": "Zip", + "input_tag": '', }, - {'field_name': 'plus4', - 'label_text': 'Plus4', - 'input_tag': '', + {"field_name": "plus4", + "label_text": "Plus4", + "input_tag": '', }, - {'field_name': 'region', - 'label_text': 'Region', - 'input_tag': '', + {"field_name": "region", + "label_text": "Region", + "input_tag": '', }, - {'field_name': 'postal', - 'label_text': 'Postal Code', - 'input_tag': '', + {"field_name": "postal", + "label_text": "Postal Code", + "input_tag": '', }, - {'field_name': 'lang', - 'label_text': 'Language', - 'input_tag': '', + {"field_name": "lang", + "label_text": "Language", + "input_tag": '', }, ], }), - 'recurring_update.html': { - 'filename': 'recurring_update.html', - 'page': { - 'title': 'Update Account Information', - 'name': 'recurring_page', - 'custom_fields': { - 'proxypassword': 'abc123' - } + "recurring_update.html": { + "filename": "recurring_update.html", + "page": { + "title": "Update Account Information", + "name": "recurring_page", + "custom_fields": { + "proxypassword": "abc123", + }, }, - 'logged_in_user': { - 'name': 'Daddy Warbucks', - 'address1': 'Easy Street', - 'email': 'daddy.warbucks@example.com', - 'city': 'New York', - 'state': 'NY', - 'phone': '555-123-1233', - 'subscriptions': subscriptions([ - {'list_id': 1}, - {'list_id': 3}, - {'list_id': 7}, - ]) + "logged_in_user": { + "name": "Daddy Warbucks", + "address1": "Easy Street", + "email": "daddy.warbucks@example.com", + "city": "New York", + "state": "NY", + "phone": "555-123-1233", + "subscriptions": subscriptions([ + {"list_id": 1}, + {"list_id": 3}, + {"list_id": 7}, + ]), }, - 'active': [{ # profile - 'id': '123', - 'payment_processor_information': { - 'use_cse': False, - 'cse_key': '123123', - 'use_tr': True, + "active": [{ # profile + "id": "123", + "payment_processor_information": { + "use_cse": False, + "cse_key": "123123", + "use_tr": True, }, - 'status': 'active', # get actual data - 'updated_at': datetime.datetime(2016, 1, 1), # get actual data - 'created_at': datetime.datetime(2016, 1, 1), # get actual data - 'start': datetime.datetime(2015, 1, 1), # get actual data - 'payment_count': 10, - 'get_period_display': 'Monthly', # get actual data - 'payment_total_amt': '$200.00', # get actual data - 'amt': '$20', - 'order': { - 'payment_method': 'cc' + "status": "active", # get actual data + "updated_at": datetime.datetime(2016, 1, 1), # get actual data + "created_at": datetime.datetime(2016, 1, 1), # get actual data + "start": datetime.datetime(2015, 1, 1), # get actual data + "payment_count": 10, + "get_period_display": "Monthly", # get actual data + "payment_total_amt": "$200.00", # get actual data + "amt": "$20", + "order": { + "payment_method": "cc", }, - 'card_num': '1234', - 'display_expiration_date': '05/2060', - 'next_payment_date': datetime.datetime(2016, 9, 1), + "card_num": "1234", + "display_expiration_date": "05/2060", + "next_payment_date": datetime.datetime(2016, 9, 1), }], - 'inactive': [], + "inactive": [], }, - 'recurring_update_paypal': { - 'filename': 'recurring_update.html', - 'page': { - 'title': 'Update Account Information (PayPal)', - 'name': 'recurring_page', + "recurring_update_paypal": { + "filename": "recurring_update.html", + "page": { + "title": "Update Account Information (PayPal)", + "name": "recurring_page", }, - 'logged_in_user': { - 'name': 'Daddy Warbucks', - 'address1': 'Easy Street', - 'email': 'daddy.warbucks@example.com', - 'city': 'New York', - 'state': 'NY', - 'phone': '555-123-1233', + "logged_in_user": { + "name": "Daddy Warbucks", + "address1": "Easy Street", + "email": "daddy.warbucks@example.com", + "city": "New York", + "state": "NY", + "phone": "555-123-1233", }, "show_paypal": True, "paypal_cohort": 0, - 'active': [{ # profile - 'account': 'MoveOnPAC PayPal', - 'id': '123', - 'payment_processor_information': { - 'use_cse': False, - 'cse_key': '123123', - 'use_tr': True, + "active": [{ # profile + "account": "MoveOnPAC PayPal", + "id": "123", + "payment_processor_information": { + "use_cse": False, + "cse_key": "123123", + "use_tr": True, }, - 'status': 'active', # get actual data - 'updated_at': datetime.datetime(2016, 1, 1), # get actual data - 'created_at': datetime.datetime(2016, 1, 1), # get actual data - 'start': datetime.datetime(2015, 1, 1), # get actual data - 'payment_count': 10, - 'get_period_display': 'Monthly', # get actual data - 'payment_total_amt': '$200.00', # get actual data - 'amt': '$20', - 'order': { - 'payment_method': 'paypal' + "status": "active", # get actual data + "updated_at": datetime.datetime(2016, 1, 1), # get actual data + "created_at": datetime.datetime(2016, 1, 1), # get actual data + "start": datetime.datetime(2015, 1, 1), # get actual data + "payment_count": 10, + "get_period_display": "Monthly", # get actual data + "payment_total_amt": "$200.00", # get actual data + "amt": "$20", + "order": { + "payment_method": "paypal", }, - 'card_num': '1234', - 'display_expiration_date': '05/2060', - 'next_payment_date': datetime.datetime(2016, 9, 1), + "card_num": "1234", + "display_expiration_date": "05/2060", + "next_payment_date": datetime.datetime(2016, 9, 1), }], - 'inactive': [], + "inactive": [], }, - 'recurring_update_ach.html': { - 'filename': 'recurring_update.html', - 'page': { - 'title': 'Update Account Information (ACH)', - 'name': 'recurring_page', - 'custom_fields': { - 'proxypassword': 'abc123' - } + "recurring_update_ach.html": { + "filename": "recurring_update.html", + "page": { + "title": "Update Account Information (ACH)", + "name": "recurring_page", + "custom_fields": { + "proxypassword": "abc123", + }, }, - 'logged_in_user': { - 'name': 'Daddy Warbucks', - 'address1': 'Easy Street', - 'email': 'daddy.warbucks@example.com', - 'city': 'New York', - 'state': 'NY', - 'phone': '555-123-1233', - 'subscriptions': subscriptions([ - {'list_id': 1}, - {'list_id': 3}, - {'list_id': 7}, - ]) + "logged_in_user": { + "name": "Daddy Warbucks", + "address1": "Easy Street", + "email": "daddy.warbucks@example.com", + "city": "New York", + "state": "NY", + "phone": "555-123-1233", + "subscriptions": subscriptions([ + {"list_id": 1}, + {"list_id": 3}, + {"list_id": 7}, + ]), }, - 'active': [{ # profile - 'id': '123', - 'is_ach': True, - 'payment_processor_information': { - 'use_cse': False, - 'cse_key': '123123', - 'use_tr': True, + "active": [{ # profile + "id": "123", + "is_ach": True, + "payment_processor_information": { + "use_cse": False, + "cse_key": "123123", + "use_tr": True, }, - 'status': 'active', #get actual data - 'updated_at': datetime.datetime(2016, 1, 1), #get actual data - 'created_at': datetime.datetime(2016, 1, 1), #get actual data - 'start': datetime.datetime(2015, 1, 1), #get actual data - 'payment_count': 10, - 'get_period_display': 'Monthly', #get actual data - 'payment_total_amt': '$200.00', #get actual data - 'amt': '$20', - 'order': { - 'payment_method': 'cc' + "status": "active", #get actual data + "updated_at": datetime.datetime(2016, 1, 1), #get actual data + "created_at": datetime.datetime(2016, 1, 1), #get actual data + "start": datetime.datetime(2015, 1, 1), #get actual data + "payment_count": 10, + "get_period_display": "Monthly", #get actual data + "payment_total_amt": "$200.00", #get actual data + "amt": "$20", + "order": { + "payment_method": "cc", }, - 'card_num': '1234', - 'display_expiration_date': '05/2060', - 'next_payment_date': datetime.datetime(2016, 9, 1), + "card_num": "1234", + "display_expiration_date": "05/2060", + "next_payment_date": datetime.datetime(2016, 9, 1), }], - 'inactive': [], + "inactive": [], }, } diff --git a/dsa_actionkit/contexts/donation_contexts.py b/dsa_actionkit/contexts/donation_contexts.py index 9877cdf..ee586e7 100644 --- a/dsa_actionkit/contexts/donation_contexts.py +++ b/dsa_actionkit/contexts/donation_contexts.py @@ -1,5 +1,4 @@ -""" -Scenarios: +"""Scenarios: 1. single 2. args 10 args.amount_other = "666" @@ -42,7 +41,7 @@ "donation_type": ["recurring", "single"], "payment_hash": ["abc123"], "suggested_ask": ["20", "666"], - "weekly": ["1"] + "weekly": ["1"], } def user(recurring=1, payment_hash=False, customfields=None, previous_recurring=False, id=666): @@ -64,30 +63,30 @@ def user(recurring=1, payment_hash=False, customfields=None, previous_recurring= "zip": "07091", "email": "morticia@example.com", "custom_fields": customfields, - } + }, } if payment_hash: - userbase['user'].update({ - 'payment_hash': 'abc123abc123', - 'has_payment_token': True, + userbase["user"].update({ + "payment_hash": "abc123abc123", + "has_payment_token": True, }) if previous_recurring==False: - userbase['user'].update({ - 'orderrecurring_set': { - 'active': { - 'count': 0, + userbase["user"].update({ + "orderrecurring_set": { + "active": { + "count": 0, + }, + "count": 0, }, - 'count': 0 - } }) else: - userbase['user'].update({ - 'orderrecurring_set': { - 'active': { - 'count': recurring, + userbase["user"].update({ + "orderrecurring_set": { + "active": { + "count": recurring, }, - 'count': recurring - } + "count": recurring, + }, }) return userbase @@ -98,8 +97,8 @@ def user(recurring=1, payment_hash=False, customfields=None, previous_recurring= "portrait_url": "https://fr.web.img2.acsta.net/medias/nmedia/18/35/61/70/19013441.jpg", "desc": "Seabright (Seab) Cooley from South Carolina and the book Advise and Consent", "id": "1959", - } - ] + }, + ], } candidates2 = { @@ -114,8 +113,8 @@ def user(recurring=1, payment_hash=False, customfields=None, previous_recurring= "portrait_url": "https://vignette.wikia.nocookie.net/simpsons/images/2/25/Adult_burns.jpg/revision/latest?cb=20111012170021", "desc": "A recurring character in the animated television series The Simpsons, and is voiced by Harry Shearer. Mr. Burns is the evil owner of the Springfield Nuclear Power Plant and is also Homer Simpson's boss.", "id": "666", - } - ] + }, + ], } products = { @@ -126,8 +125,8 @@ def user(recurring=1, payment_hash=False, customfields=None, previous_recurring= "desc": "This is a cool product that you should want", "price": "55.23", "id": "1", - } - ] + }, + ], } products2 = { @@ -137,19 +136,19 @@ def user(recurring=1, payment_hash=False, customfields=None, previous_recurring= {"name": "This fight is our fight: the battle to save america's middle class", "desc": "This is a cool product that you should want", "price": "55.23", - "id": "1" + "id": "1", }, {"name": "no desc max 1", "price": "1", "max": 1, - "id": "2" - } - ] + "id": "2", + }, + ], } -def base(title='', entity='c4', layout='', filename="donate.html", fields={}, show_paypal=False, allow_international=False, accept_ach=False, liveaddress=None): +def base(title="", entity="c4", layout="", filename="donate.html", fields={}, show_paypal=False, allow_international=False, accept_ach=False, liveaddress=None): rv = { "filename": filename, "show_paypal": show_paypal, @@ -161,11 +160,11 @@ def base(title='', entity='c4', layout='', filename="donate.html", fields={}, sh "custom_fields": { "layout_options": "2col,no_social,%s" % layout, "entity": entity, # "pac", "joint_pac_c4", - "liveaddress": liveaddress + "liveaddress": liveaddress, #"thanks_header_text": "You are the best!", #optional #"sharing_prompt": False, #optional }, - "title": 'Donate to Example.com (%s)' % title, + "title": "Donate to Example.com (%s)" % title, "name": "civ-donation", "id": 123, "currency_sym": "$", @@ -179,50 +178,50 @@ def base(title='', entity='c4', layout='', filename="donate.html", fields={}, sh "amounts": [20,40,75,200,400,750,1500,"other"], "allow_monthly": True, } - rv['page']['custom_fields'].update(fields) + rv["page"]["custom_fields"].update(fields) return rv -def order(order_type='order', details=None, quickpay=False, paypal=False, apple=False): #get rid of paypal and applepay and switch to "payment method" +def order(order_type="order", details=None, quickpay=False, paypal=False, apple=False): #get rid of paypal and applepay and switch to "payment method" #order_type = 'orderrecurring' orderkey = { - 'order': { - 'id': 123456, - 'amt': '$12.07', - 'created_at': datetime.datetime.now(), - 'account': 'Example.com Civic Action', - } + "order": { + "id": 123456, + "amt": "$12.07", + "created_at": datetime.datetime.now(), + "account": "Example.com Civic Action", + }, } - if order_type == 'orderrecurring': - orderkey['orderrecurring'] = orderkey['order'] + if order_type == "orderrecurring": + orderkey["orderrecurring"] = orderkey["order"] if details: orderkey[order_type].update(details) rv = { - 'akid': '--userakidTEST--', - 'action': { - 'id': 654321, - 'custom_fields': { - 'upgrade_order_id': '111', - 'add_me_to_weekly': True, #optional + "akid": "--userakidTEST--", + "action": { + "id": 654321, + "custom_fields": { + "upgrade_order_id": "111", + "add_me_to_weekly": True, #optional }, - } + }, } if quickpay: - rv['action']['custom_fields'].update({ - 'payment_token': { - 'status': 'active', - 'token': 'abc123999', + rv["action"]["custom_fields"].update({ + "payment_token": { + "status": "active", + "token": "abc123999", }, }) if paypal: - rv['action']['custom_fields'].update({ - 'ak_paypal_transaction_id': '2309147283', + rv["action"]["custom_fields"].update({ + "ak_paypal_transaction_id": "2309147283", }) if apple: - rv['action']['custom_fields'].update({ - 'mobile_payment': 'apple_pay', + rv["action"]["custom_fields"].update({ + "mobile_payment": "apple_pay", }) rv.update(orderkey) - rv['action'].update(orderkey) + rv["action"].update(orderkey) return rv def compose(bases, argparams=[], argind=0): @@ -230,70 +229,70 @@ def compose(bases, argparams=[], argind=0): for b in bases: rv.update(b) arg_dict = dict([(k,args_permutations[k][argind]) for k in argparams]) - rv.update({'args': arg_dict}) + rv.update({"args": arg_dict}) return rv contexts = { - 'donate.1': compose([base('civ')]), - 'donate.2': compose([base('candidate', entity='pac'), candidates]), - 'donate.3': compose([base('suggested_ask')], ["suggested_ask",]), - 'donate.4': compose([base('suggested_ask, recurring')], ["suggested_ask","donation_type"]), - 'donate.5': compose([base('other suggested_ask, single')], ["suggested_ask","donation_type"], -1), - 'donate.6': compose([base('suggested_ask, payment_hash'), user(0, payment_hash=True)], ["suggested_ask","payment_hash"]), - 'donate.7': compose([base('user'), user()]), - 'donate.8': compose([base('pac', entity='pac', show_paypal=True), user(id=507809)]), - 'donate.9': compose([base('candidate suggested', entity='pac', layout='donate_5050_split'), candidates], ["suggested_ask"], -1), - 'donate.10': compose([base('two candidates suggested', entity='pac', layout='donate_5050_split'), user(id=507809), candidates2], ["suggested_ask"], -1), - 'donate.11': compose([base('two candidates suggested no 5050', entity='pac'), candidates2], ["suggested_ask"], -1), - 'donate.12': compose([base('candidate, quickpay', entity='pac', layout='donate_5050_split'), user(0, payment_hash=True), candidates], ["payment_hash"], -1), - 'donate.13': compose([base('two candidates quickpay', entity='pac', layout='donate_5050_split'), user(0, payment_hash=True), candidates2], ["payment_hash"], -1), - 'donate.14': compose([base('1 product', liveaddress="shipping"), products]), - 'donate.15': compose([base('2 products', liveaddress="shipping"), products2]), - 'donate.16': compose([base('weekly recurring checkbox', layout="make_weekly_checkbox")], ["weekly"]), - 'donate.17': compose([base('quickpay recurring checkbox', entity='pac', layout="donate_5050_split"), user(0, payment_hash=True), candidates], ["payment_hash"], -1), - 'donate.18': compose([base('quickpay', entity='pac', layout='donate_5050_split donation_no_checkbox'), user(0, payment_hash=True), candidates], ["payment_hash"], -1), - 'donate.19': compose([base('quickpay with weekly', entity='pac', layout="make_weekly_checkbox"), user(0, payment_hash=True), candidates], ["payment_hash"], -1), - 'donate.20': compose([base('quickpay', entity='pac', layout='weekly_only'), user(0, payment_hash=True), candidates], ["payment_hash"], -1), - 'donate.22': compose([base('quickpay with monthly recurring'), user(0, payment_hash=True)], ["donation_type","payment_hash"]), - 'donate.23': compose([base('civ', show_paypal=True), user(0, id=5079)]), - 'donate.24': compose([base('civ with international', allow_international=True)]), - 'donate.25': compose([base('pac', entity='pac', show_paypal=True)]), - 'donate.26': compose([base('weekly and two candidates', entity='pac', layout="weekly_only"), candidates2]), - 'donate.27': compose([base('two candidates', entity='pac'), candidates2]), - 'donate.28': compose([base('pac', entity='pac', show_paypal=True, layout="accept_ach"), user(id=507809)]), - 'donate.29': compose([base('pac', entity='pac', show_paypal=True), user(id=507810)]), - 'donate.30': compose([base('pac with ach option', entity='pac', accept_ach=True), user(id=507809)]), - 'donate.31': compose([base('quickpay with a good weekly param combination', entity='pac', layout='weekly_only'), user(0, payment_hash=True), candidates], ["donation_type","payment_hash"]), - 'donate.32': compose([base('quickpay with a bad weekly param combination', entity='pac', layout='weekly_only'), user(0, payment_hash=True), candidates], ["payment_hash"]), - 'donate.thanks.1': compose([base('civ with payment_hash', filename='thanks.html'), user(0, payment_hash=True), order()]), - 'donate.thanks.2': compose([base('recurring civ', entity='pac', filename='thanks.html'), - user(), order('orderrecurring')]), - 'donate.thanks.3': compose([base('recurring civ receipt message', - entity='pac', filename='thanks.html', - fields={'thanks_below_receipt_message':'This message is below the receipt!'} + "donate.1": compose([base("civ")]), + "donate.2": compose([base("candidate", entity="pac"), candidates]), + "donate.3": compose([base("suggested_ask")], ["suggested_ask"]), + "donate.4": compose([base("suggested_ask, recurring")], ["suggested_ask","donation_type"]), + "donate.5": compose([base("other suggested_ask, single")], ["suggested_ask","donation_type"], -1), + "donate.6": compose([base("suggested_ask, payment_hash"), user(0, payment_hash=True)], ["suggested_ask","payment_hash"]), + "donate.7": compose([base("user"), user()]), + "donate.8": compose([base("pac", entity="pac", show_paypal=True), user(id=507809)]), + "donate.9": compose([base("candidate suggested", entity="pac", layout="donate_5050_split"), candidates], ["suggested_ask"], -1), + "donate.10": compose([base("two candidates suggested", entity="pac", layout="donate_5050_split"), user(id=507809), candidates2], ["suggested_ask"], -1), + "donate.11": compose([base("two candidates suggested no 5050", entity="pac"), candidates2], ["suggested_ask"], -1), + "donate.12": compose([base("candidate, quickpay", entity="pac", layout="donate_5050_split"), user(0, payment_hash=True), candidates], ["payment_hash"], -1), + "donate.13": compose([base("two candidates quickpay", entity="pac", layout="donate_5050_split"), user(0, payment_hash=True), candidates2], ["payment_hash"], -1), + "donate.14": compose([base("1 product", liveaddress="shipping"), products]), + "donate.15": compose([base("2 products", liveaddress="shipping"), products2]), + "donate.16": compose([base("weekly recurring checkbox", layout="make_weekly_checkbox")], ["weekly"]), + "donate.17": compose([base("quickpay recurring checkbox", entity="pac", layout="donate_5050_split"), user(0, payment_hash=True), candidates], ["payment_hash"], -1), + "donate.18": compose([base("quickpay", entity="pac", layout="donate_5050_split donation_no_checkbox"), user(0, payment_hash=True), candidates], ["payment_hash"], -1), + "donate.19": compose([base("quickpay with weekly", entity="pac", layout="make_weekly_checkbox"), user(0, payment_hash=True), candidates], ["payment_hash"], -1), + "donate.20": compose([base("quickpay", entity="pac", layout="weekly_only"), user(0, payment_hash=True), candidates], ["payment_hash"], -1), + "donate.22": compose([base("quickpay with monthly recurring"), user(0, payment_hash=True)], ["donation_type","payment_hash"]), + "donate.23": compose([base("civ", show_paypal=True), user(0, id=5079)]), + "donate.24": compose([base("civ with international", allow_international=True)]), + "donate.25": compose([base("pac", entity="pac", show_paypal=True)]), + "donate.26": compose([base("weekly and two candidates", entity="pac", layout="weekly_only"), candidates2]), + "donate.27": compose([base("two candidates", entity="pac"), candidates2]), + "donate.28": compose([base("pac", entity="pac", show_paypal=True, layout="accept_ach"), user(id=507809)]), + "donate.29": compose([base("pac", entity="pac", show_paypal=True), user(id=507810)]), + "donate.30": compose([base("pac with ach option", entity="pac", accept_ach=True), user(id=507809)]), + "donate.31": compose([base("quickpay with a good weekly param combination", entity="pac", layout="weekly_only"), user(0, payment_hash=True), candidates], ["donation_type","payment_hash"]), + "donate.32": compose([base("quickpay with a bad weekly param combination", entity="pac", layout="weekly_only"), user(0, payment_hash=True), candidates], ["payment_hash"]), + "donate.thanks.1": compose([base("civ with payment_hash", filename="thanks.html"), user(0, payment_hash=True), order()]), + "donate.thanks.2": compose([base("recurring civ", entity="pac", filename="thanks.html"), + user(), order("orderrecurring")]), + "donate.thanks.3": compose([base("recurring civ receipt message", + entity="pac", filename="thanks.html", + fields={"thanks_below_receipt_message":"This message is below the receipt!"}, ), - user(), order('orderrecurring')]), - 'donate.thanks.4': compose([base('recurring user recurring', filename='thanks.html'), - user(2), order('orderrecurring')]), - 'donate.thanks.5': compose([base('pac user payment_hash', entity='pac', filename='thanks.html'), + user(), order("orderrecurring")]), + "donate.thanks.4": compose([base("recurring user recurring", filename="thanks.html"), + user(2), order("orderrecurring")]), + "donate.thanks.5": compose([base("pac user payment_hash", entity="pac", filename="thanks.html"), user(0, payment_hash=True), order()]), - 'donate.thanks.6': compose([base('pac user quickpay no employer', entity='pac', filename='thanks.html'), - user(0, payment_hash=True, customfields={'x':1}), order(quickpay=True)]), - 'donate.thanks.7': compose([base('pac user candidate', entity='pac', filename='thanks.html'), + "donate.thanks.6": compose([base("pac user quickpay no employer", entity="pac", filename="thanks.html"), + user(0, payment_hash=True, customfields={"x":1}), order(quickpay=True)]), + "donate.thanks.7": compose([base("pac user candidate", entity="pac", filename="thanks.html"), user(0, payment_hash=True), order(details={ - 'order_details': [ - {'candidate': {'name': "Francis Underwood"}, - 'amount': 10.00,}, + "order_details": [ + {"candidate": {"name": "Francis Underwood"}, + "amount": 10.00}, ], - 'other_amount': 2.07 + "other_amount": 2.07, })]), - 'donate.thanks.8': compose([base('civ with payment_hash', filename='thanks.html'), user(0, payment_hash=True), order()]), - 'donate.thanks.9': compose([base('civ with payment_hash', filename='thanks.html'), user(recurring=0, payment_hash=True, previous_recurring=False), order(paypal=True)]), - 'donate.thanks.10': compose([base('civ with payment_hash', filename='thanks.html'), user(recurring=1, payment_hash=True, previous_recurring=True), order(paypal=True)]), - 'donate.thanks.11': compose([base('civ with payment_hash', filename='thanks.html'), user(recurring=0, payment_hash=True, previous_recurring=False), order()]), - 'donate.thanks.12': compose([base('civ with payment_hash', filename='thanks.html'), user(recurring=1, payment_hash=True, previous_recurring=True), order()]), - 'donate.thanks.13': compose([base('civ with payment_hash', filename='thanks.html'), user(recurring=1, payment_hash=True, previous_recurring=False), order(apple=True)]), - 'donate.thanks.14': compose([base('civ with payment_hash', filename='thanks.html'), user(recurring=1, payment_hash=True, previous_recurring=True), order(apple=True)]), + "donate.thanks.8": compose([base("civ with payment_hash", filename="thanks.html"), user(0, payment_hash=True), order()]), + "donate.thanks.9": compose([base("civ with payment_hash", filename="thanks.html"), user(recurring=0, payment_hash=True, previous_recurring=False), order(paypal=True)]), + "donate.thanks.10": compose([base("civ with payment_hash", filename="thanks.html"), user(recurring=1, payment_hash=True, previous_recurring=True), order(paypal=True)]), + "donate.thanks.11": compose([base("civ with payment_hash", filename="thanks.html"), user(recurring=0, payment_hash=True, previous_recurring=False), order()]), + "donate.thanks.12": compose([base("civ with payment_hash", filename="thanks.html"), user(recurring=1, payment_hash=True, previous_recurring=True), order()]), + "donate.thanks.13": compose([base("civ with payment_hash", filename="thanks.html"), user(recurring=1, payment_hash=True, previous_recurring=False), order(apple=True)]), + "donate.thanks.14": compose([base("civ with payment_hash", filename="thanks.html"), user(recurring=1, payment_hash=True, previous_recurring=True), order(apple=True)]), } diff --git a/dsa_actionkit/contexts/event_context_json.py b/dsa_actionkit/contexts/event_context_json.py index 20d164f..031274a 100644 --- a/dsa_actionkit/contexts/event_context_json.py +++ b/dsa_actionkit/contexts/event_context_json.py @@ -1,4 +1,4 @@ -#this is for /context/ loading for updating page in +#this is for /context/ loading for updating page in #https://roboticdogs.actionkit.com/context/test_create?callback=actionkit.forms.onContextLoaded&form_name=act&action_id=117202230&ar=1&required=email&required=country&want_prefill_data=1&r=0.20345950596532325&url=https://roboticdogs.actionkit.com/event/scott-test_create/create/?action_id=117202230&update=1&want_prefill_data=1 #should be wrapped in actionkit.forms.onContextLoaded() event_json = { @@ -75,14 +75,14 @@ "work_phone": 1, "x": 1, "y": 1, - "zip": 1 + "zip": 1, }, "blank": [ "suffix", "prefix", "middle_name", "address2", - "region" + "region", ], "form_name": "act", "move_fields": [], @@ -91,8 +91,8 @@ "page": { "custom_fields": { "entity": "pac", - "test_custom_event_field": "random text up to 100 characters" - } + "test_custom_event_field": "random text up to 100 characters", + }, }, "prefill_data": { "action_id": "117202230", @@ -144,7 +144,7 @@ "prefix": "", "state": "CO", "suffix": "", - "zip": "80210" + "zip": "80210", }, "required": [ "event_starts_at_date", @@ -155,7 +155,7 @@ "event_starts_at_time", "event_starts_at_ampm", "event_host_requirements", - "event_venue" + "event_venue", ], "text": { "error_TEMPLATE:invalid": "{0} is invalid.", @@ -258,6 +258,6 @@ "field_shipping_zip": "shipping ZIP Code", "field_state": "state", "field_taf_emails": "one or more friends' email addresses", - "field_zip": "ZIP Code" - } + "field_zip": "ZIP Code", + }, } diff --git a/dsa_actionkit/contexts/event_contexts.py b/dsa_actionkit/contexts/event_contexts.py index fdb5593..6e33c50 100644 --- a/dsa_actionkit/contexts/event_contexts.py +++ b/dsa_actionkit/contexts/event_contexts.py @@ -3,17 +3,17 @@ import os import random -from django.utils import timezone -from django.utils import dateformat +from django.utils import dateformat, timezone from django.utils.html import format_html + class signups(list): pass class user(dict): def __str__(self): - return self.get('name') + return self.get("name") attendees = signups([ # "role": "attendee", @@ -34,7 +34,7 @@ def __str__(self): }), }, ]) -attendees.role = 'attendee' +attendees.role = "attendee" cohosts = signups([ { @@ -46,10 +46,10 @@ def __str__(self): }), }, ]) -cohosts.role = 'host' +cohosts.role = "host" # 1000 based off of congressional district offices. lat/lng are not accurate, but nearby -places_list = list(csv.DictReader(open(os.path.dirname(__file__) + '/event_places.csv'))) +places_list = list(csv.DictReader(open(os.path.dirname(__file__) + "/event_places.csv"))) class MST(datetime.tzinfo): # use MST because AZ is in MST and doesn't observe DST @@ -77,12 +77,10 @@ def event_create(days_from_now=7, localtime=15, id=343775, is_awaiting_confirmation=False, place_index=None, minutes_from_now=False, attend_page=False): - - """ - localtime = hour of the day - To get an event time with more precision to the current time, - set days_from_now=0 and minutes_from_now to an integer, and - choose a place_index with an MST locale. + """Localtime = hour of the day + To get an event time with more precision to the current time, + set days_from_now=0 and minutes_from_now to an integer, and + choose a place_index with an MST locale. """ now_utc = datetime.datetime.now(timezone.utc) @@ -93,8 +91,8 @@ def event_create(days_from_now=7, localtime=15, id=343775, place_loc = places_list[place_index] else: place_loc = places_list[random.randint(0, len(places_list) -1)] - place_loc['city_etc_no_postal'] = '{}, {}'.format(place_loc['city'], place_loc['state']) - place_loc['city_etc'] = '{} {}'.format(place_loc['city_etc_no_postal'], place_loc['zip']) + place_loc["city_etc_no_postal"] = "{}, {}".format(place_loc["city"], place_loc["state"]) + place_loc["city_etc"] = "{} {}".format(place_loc["city_etc_no_postal"], place_loc["zip"]) objobj = None @@ -123,7 +121,7 @@ def event_create(days_from_now=7, localtime=15, id=343775, # "latitude": "directions": "Directions.", - "get_starts_at_display": dateformat.format(event_day, 'l, M j, g:i A'), # "Monday, Jan 1, 1:00 AM", + "get_starts_at_display": dateformat.format(event_day, "l, M j, g:i A"), # "Monday, Jan 1, 1:00 AM", "is_in_past": bool(now_utc > event_day_utc), "is_full": bool(attendee_count >= max_attendees), "is_open_for_signup": bool(days_from_now > 0 and not attendee_count >= max_attendees), @@ -132,22 +130,22 @@ def event_create(days_from_now=7, localtime=15, id=343775, "is_awaiting_confirmation": is_awaiting_confirmation, "note_to_attendees": "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.", "public_description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.", - "title": "Event Title {}".format(place_index), + "title": f"Event Title {place_index}", "venue": "Venue Name", "local_campaign": { "create_page": { - "name": "Local Event Creation Name" + "name": "Local Event Creation Name", }, "signup_page": { - "name": "Local Signup Page Name" - } + "name": "Local Signup Page Name", + }, }, } evt_obj.update(place_loc) return evt_obj contexts = { - 'event_host_tools.html': { + "event_host_tools.html": { "akid": "111111", "filename": "event_host_tools.html", "page": { @@ -156,11 +154,11 @@ def event_create(days_from_now=7, localtime=15, id=343775, }, "followup": { "taf_subject": "Come to my event!", - "taf_body": "Hi, blah blah blah about the event!!
[[See the 'Tell-a-friend Body' in After-Action Info for the Host page of this event.]]" + "taf_body": "Hi, blah blah blah about the event!!
[[See the 'Tell-a-friend Body' in After-Action Info for the Host page of this event.]]", }, "title": "Host Tools Page", "type": "EventCreate", - "name": "fakecampaign_create" + "name": "fakecampaign_create", }, "attendees": attendees, "cohosts": cohosts, @@ -182,7 +180,7 @@ def event_create(days_from_now=7, localtime=15, id=343775, "phone": "123-456-7890", }), }, - 'event_attend.html': { + "event_attend.html": { "filename": "event_attend.html", "campaign": { "local_title": "Campaign Title", @@ -199,42 +197,42 @@ def event_create(days_from_now=7, localtime=15, id=343775, "events": [event_create(place_index=20)], "form": { "signup_text": "

Signup text.

", - "ground_rules": "

Please follow these guidelines to ensure a good event:

" + "ground_rules": "

Please follow these guidelines to ensure a good event:

", }, "context": { - "required": 'email' + "required": "email", }, - 'user_fields': [ - {'field_name': 'name', - 'label_text': 'Name', - 'input_tag': '', - 'input_html': format_html(''), + "user_fields": [ + {"field_name": "name", + "label_text": "Name", + "input_tag": '', + "input_html": format_html(''), }, - {'field_name': 'email', - 'label_text': 'Email Address', - 'input_tag': '', - 'input_html': format_html(''), + {"field_name": "email", + "label_text": "Email Address", + "input_tag": '', + "input_html": format_html(''), }, - {'field_name': 'address1', - 'label_text': 'Street Address', - 'input_tag': '', - 'input_html': format_html(''), + {"field_name": "address1", + "label_text": "Street Address", + "input_tag": '', + "input_html": format_html(''), }, - {'field_name': 'zip', - 'label_text': 'ZIP Code', - 'input_tag': '', - 'input_html': format_html(''), + {"field_name": "zip", + "label_text": "ZIP Code", + "input_tag": '', + "input_html": format_html(''), }, - {'field_name': 'phone', - 'label_text': 'Phone', - 'input_tag': '', - 'input_html': format_html(''), + {"field_name": "phone", + "label_text": "Phone", + "input_tag": '', + "input_html": format_html(''), }, ], "page": { "title": "Event Attend (standard)", "type": "EventSignup", - "name": "fakecampaign_attend" + "name": "fakecampaign_attend", }, "logged_in_user":user({ "name": "Current user", @@ -245,7 +243,7 @@ def event_create(days_from_now=7, localtime=15, id=343775, "phone": "123-456-7890", }), }, - 'event_attend_inactive.html': { + "event_attend_inactive.html": { "filename": "event_attend.html", "campaign": { "local_title": "Campaign Title", @@ -262,37 +260,37 @@ def event_create(days_from_now=7, localtime=15, id=343775, "events": [event_create(place_index=20, is_inactive=True)], "form": { "signup_text": "

Signup text.

", - "ground_rules": "

Please follow these guidelines to ensure a good event:

" + "ground_rules": "

Please follow these guidelines to ensure a good event:

", }, "context": { - "required": 'email' + "required": "email", }, - 'user_fields': [ - {'field_name': 'name', - 'label_text': 'Name', - 'input_tag': '', + "user_fields": [ + {"field_name": "name", + "label_text": "Name", + "input_tag": '', }, - {'field_name': 'email', - 'label_text': 'Email Address', - 'input_tag': '', + {"field_name": "email", + "label_text": "Email Address", + "input_tag": '', }, - {'field_name': 'address1', - 'label_text': 'Street Address', - 'input_tag': '', + {"field_name": "address1", + "label_text": "Street Address", + "input_tag": '', }, - {'field_name': 'zip', - 'label_text': 'ZIP Code', - 'input_tag': '', + {"field_name": "zip", + "label_text": "ZIP Code", + "input_tag": '', }, - {'field_name': 'phone', - 'label_text': 'Phone', - 'input_tag': '', + {"field_name": "phone", + "label_text": "Phone", + "input_tag": '', }, ], "page": { "title": "Event Attend (cancelled event)", "type": "EventSignup", - "name": "fakecampaign_attend" + "name": "fakecampaign_attend", }, "logged_in_user":user({ "name": "Current user", @@ -303,7 +301,7 @@ def event_create(days_from_now=7, localtime=15, id=343775, "phone": "123-456-7890", }), }, - 'event_attend_past_event.html': { + "event_attend_past_event.html": { "filename": "event_attend.html", "campaign": { "local_title": "Campaign Title", @@ -320,37 +318,37 @@ def event_create(days_from_now=7, localtime=15, id=343775, "events": [event_create(-2, place_index=20)], "form": { "signup_text": "

Signup text for past event.

", - "ground_rules": "

Please follow these guidelines to ensure a good event:

" + "ground_rules": "

Please follow these guidelines to ensure a good event:

", }, "context": { - "required": 'email' + "required": "email", }, - 'user_fields': [ - {'field_name': 'name', - 'label_text': 'Name', - 'input_tag': '', + "user_fields": [ + {"field_name": "name", + "label_text": "Name", + "input_tag": '', }, - {'field_name': 'email', - 'label_text': 'Email Address', - 'input_tag': '', + {"field_name": "email", + "label_text": "Email Address", + "input_tag": '', }, - {'field_name': 'address1', - 'label_text': 'Street Address', - 'input_tag': '', + {"field_name": "address1", + "label_text": "Street Address", + "input_tag": '', }, - {'field_name': 'zip', - 'label_text': 'ZIP Code', - 'input_tag': '', + {"field_name": "zip", + "label_text": "ZIP Code", + "input_tag": '', }, - {'field_name': 'phone', - 'label_text': 'Phone', - 'input_tag': '', + {"field_name": "phone", + "label_text": "Phone", + "input_tag": '', }, ], "page": { "title": "Event Attend (past event)", "type": "EventSignup", - "name": "fakecampaign_attend" + "name": "fakecampaign_attend", }, "logged_in_user":user({ "name": "Current user", @@ -361,7 +359,7 @@ def event_create(days_from_now=7, localtime=15, id=343775, "phone": "123-456-7890", }), }, - 'event_attend_past_event_same_day.html': { + "event_attend_past_event_same_day.html": { "filename": "event_attend.html", "campaign": { "local_title": "Campaign Title", @@ -378,37 +376,37 @@ def event_create(days_from_now=7, localtime=15, id=343775, "events": [event_create(0, 15, place_index=20, minutes_from_now=-20)], "form": { "signup_text": "

Signup text for past event.

", - "ground_rules": "

Please follow these guidelines to ensure a good event:

" + "ground_rules": "

Please follow these guidelines to ensure a good event:

", }, "context": { - "required": 'email' + "required": "email", }, - 'user_fields': [ - {'field_name': 'name', - 'label_text': 'Name', - 'input_tag': '', + "user_fields": [ + {"field_name": "name", + "label_text": "Name", + "input_tag": '', }, - {'field_name': 'email', - 'label_text': 'Email Address', - 'input_tag': '', + {"field_name": "email", + "label_text": "Email Address", + "input_tag": '', }, - {'field_name': 'address1', - 'label_text': 'Street Address', - 'input_tag': '', + {"field_name": "address1", + "label_text": "Street Address", + "input_tag": '', }, - {'field_name': 'zip', - 'label_text': 'ZIP Code', - 'input_tag': '', + {"field_name": "zip", + "label_text": "ZIP Code", + "input_tag": '', }, - {'field_name': 'phone', - 'label_text': 'Phone', - 'input_tag': '', + {"field_name": "phone", + "label_text": "Phone", + "input_tag": '', }, ], "page": { "title": "Event Attend (past event same day)", "type": "EventSignup", - "name": "fakecampaign_attend" + "name": "fakecampaign_attend", }, "logged_in_user":user({ "name": "Current user", @@ -419,7 +417,7 @@ def event_create(days_from_now=7, localtime=15, id=343775, "phone": "123-456-7890", }), }, - 'event_attendee_tools.html': { + "event_attendee_tools.html": { "akid": "111111", "filename": "event_attendee_tools.html", "campaign": { @@ -456,7 +454,7 @@ def event_create(days_from_now=7, localtime=15, id=343775, "phone": "123-456-7890", }), }, - 'event_search.html': { + "event_search.html": { "filename": "event_search.html", "form": { "search_page_text": "

Search page text for campaign with only future events.

", @@ -476,18 +474,18 @@ def event_create(days_from_now=7, localtime=15, id=343775, "show_zip": True, "show_public_description": True, "name": "fakecampaign-with-future-events", - "public_create_page": True + "public_create_page": True, }, "events": [event_create(1, 10, 343123), event_create(1, 15, 343124), event_create(4, 15, 343125), - event_create(0, 15, 343130, place_index=57, minutes_from_now=5) + event_create(0, 15, 343130, place_index=57, minutes_from_now=5), ], }, - 'event_search_with_results': { + "event_search_with_results": { "filename": "event_search.html", "args": { - "page": "event_search" + "page": "event_search", }, "hide_map": False, "campaign": { @@ -500,12 +498,12 @@ def event_create(days_from_now=7, localtime=15, id=343775, "show_zip": True, "show_public_description": True, "name": "fakecampaign-with-future-events", - "public_create_page": True + "public_create_page": True, }, "events": [event_create(1, 10, 343123), event_create(1, 15, 343124), event_create(4, 15, 343125), - event_create(0, 15, 343130, place_index=57, minutes_from_now=5) + event_create(0, 15, 343130, place_index=57, minutes_from_now=5), ], "form": { "search_page_text": "

Search page text for campaign with only future events.

", @@ -516,10 +514,10 @@ def event_create(days_from_now=7, localtime=15, id=343775, "type": "EventSignup", }, }, - 'event_search_with_results_showaddress1': { + "event_search_with_results_showaddress1": { "filename": "event_search.html", "args": { - "page": "event_search" + "page": "event_search", }, "hide_map": False, "campaign": { @@ -533,12 +531,12 @@ def event_create(days_from_now=7, localtime=15, id=343775, "show_address1": True, # to support map in Original template "show_public_description": True, "name": "fakecampaign-with-future-events", - "public_create_page": True + "public_create_page": True, }, "events": [event_create(1, 10, 343123, place_index=126), event_create(1, 15, 343124, place_index=43), event_create(4, 15, 343125, place_index=645), - event_create(0, 15, 343130, place_index=57, minutes_from_now=5) + event_create(0, 15, 343130, place_index=57, minutes_from_now=5), ], "form": { "search_page_text": "

Search page text for campaign with only future events.

", @@ -549,7 +547,7 @@ def event_create(days_from_now=7, localtime=15, id=343775, "type": "EventSignup", }, }, - 'event_search_noevents.html': { + "event_search_noevents.html": { # this doesn't render as expected - come back to this later "filename": "event_search.html", "form": { @@ -570,13 +568,13 @@ def event_create(days_from_now=7, localtime=15, id=343775, "show_zip": True, "show_public_description": True, "name": "fakecampaign-with-no-events", - "public_create_page": True + "public_create_page": True, }, }, - 'event_search_with_no_results': { + "event_search_with_no_results": { "filename": "event_search.html", "args": { - "page": "event_search" + "page": "event_search", }, "campaign": { "local_title": "Campaign Title - no events", @@ -587,7 +585,7 @@ def event_create(days_from_now=7, localtime=15, id=343775, "show_city": True, "show_zip": True, "show_public_description": True, - "name": "fakecampaign-with-no-events" + "name": "fakecampaign-with-no-events", }, "events": [], "form": { @@ -599,7 +597,7 @@ def event_create(days_from_now=7, localtime=15, id=343775, "type": "EventSignup", }, }, - 'event_search_past_events_only.html': { + "event_search_past_events_only.html": { "filename": "event_search.html", "form": { "search_page_text": "

Search page text for campaign with only past events.

", @@ -612,7 +610,7 @@ def event_create(days_from_now=7, localtime=15, id=343775, "events": [event_create(-1, 10, 343126), event_create(-7, 15, 343127), event_create(-5, 15, 343128), - event_create(0, 15, 343129, place_index=57, minutes_from_now=-5) + event_create(0, 15, 343129, place_index=57, minutes_from_now=-5), ], "campaign": { "local_title": "Campaign Title", @@ -623,13 +621,13 @@ def event_create(days_from_now=7, localtime=15, id=343775, "show_city": True, "show_zip": True, "show_public_description": True, - "name": "resistandwin-volunteerday" + "name": "resistandwin-volunteerday", }, }, - 'event_search_with_results_past_events_only': { + "event_search_with_results_past_events_only": { "filename": "event_search.html", "args": { - "page": "event_search" + "page": "event_search", }, "campaign": { "local_title": "Campaign Title", @@ -640,12 +638,12 @@ def event_create(days_from_now=7, localtime=15, id=343775, "show_city": True, "show_zip": True, "show_public_description": True, - "name": "resistandwin-volunteerday" + "name": "resistandwin-volunteerday", }, "events": [event_create(-1, 10, 343126), event_create(-7, 15, 343127), event_create(-5, 15, 343128), - event_create(0, 15, 343129, place_index=57, minutes_from_now=-5) + event_create(0, 15, 343129, place_index=57, minutes_from_now=-5), ], "form": { "search_page_text": "

Search page text for campaign with only past events.

", @@ -656,7 +654,7 @@ def event_create(days_from_now=7, localtime=15, id=343775, "type": "EventSignup", }, }, - 'event_search_past_and_future_events.html': { + "event_search_past_and_future_events.html": { "filename": "event_search.html", "form": { "search_page_text": "

Search page text for campaign with past and future events.

", @@ -671,7 +669,7 @@ def event_create(days_from_now=7, localtime=15, id=343775, event_create(-5, 15, 343128), event_create(1, 15, 343123), event_create(3, 15, 343124), - event_create(3, 10, 343125) + event_create(3, 10, 343125), ], "campaign": { "local_title": "Campaign Title - Campaign with past and future events", @@ -682,13 +680,13 @@ def event_create(days_from_now=7, localtime=15, id=343775, "show_city": True, "show_zip": True, "show_public_description": True, - "name": "resistandwin-volunteerday" + "name": "resistandwin-volunteerday", }, }, - 'event_search_with_results_past_and_future_events': { + "event_search_with_results_past_and_future_events": { "filename": "event_search.html", "args": { - "page": "event_search" + "page": "event_search", }, "campaign": { "local_title": "Campaign Title", @@ -699,14 +697,14 @@ def event_create(days_from_now=7, localtime=15, id=343775, "show_city": True, "show_zip": True, "show_public_description": True, - "name": "resistandwin-volunteerday" + "name": "resistandwin-volunteerday", }, "events": [event_create(-1, 10, 343126), event_create(-7, 15, 343127), event_create(-5, 15, 343128), event_create(1, 15, 343123), event_create(3, 15, 343124), - event_create(3, 10, 343125) + event_create(3, 10, 343125), ], "form": { "search_page_text": "

Search page text for campaign with only past events.

", @@ -717,11 +715,11 @@ def event_create(days_from_now=7, localtime=15, id=343775, "type": "EventSignup", }, }, - 'event_search_with_api_broken': { + "event_search_with_api_broken": { "500_API": True, "filename": "event_search.html", "args": { - "page": "event_search" + "page": "event_search", }, "campaign": { "local_title": "Campaign Title - no events", @@ -732,7 +730,7 @@ def event_create(days_from_now=7, localtime=15, id=343775, "show_city": True, "show_zip": True, "show_public_description": True, - "name": "fakecampaign-with-no-events" + "name": "fakecampaign-with-no-events", }, "events": [], "form": { @@ -744,7 +742,7 @@ def event_create(days_from_now=7, localtime=15, id=343775, "type": "EventSignup", }, }, - 'event_search_with_mueller_load.html': { + "event_search_with_mueller_load.html": { "filename": "event_search.html", "form": { "search_page_text": "

Search page text for campaign with 1000 events.

", @@ -764,13 +762,13 @@ def event_create(days_from_now=7, localtime=15, id=343775, "show_city": True, "show_zip": True, "show_public_description": True, - "name": "fakecampaign-mueller_load_events" + "name": "fakecampaign-mueller_load_events", }, }, - 'event_search_with_mueller_load_past.html': { + "event_search_with_mueller_load_past.html": { "filename": "event_search.html", "args": { - "page": "event_search" + "page": "event_search", }, "campaign": { "local_title": "Campaign Title", @@ -781,7 +779,7 @@ def event_create(days_from_now=7, localtime=15, id=343775, "show_city": True, "show_zip": True, "show_public_description": True, - "name": "fakecampaign-mueller_load_events" + "name": "fakecampaign-mueller_load_events", }, "events": [event_create(0, 17, 10000+place, place_index=place, minutes_from_now=-(place*2)) for place in range(1000)], "form": { @@ -793,7 +791,7 @@ def event_create(days_from_now=7, localtime=15, id=343775, "type": "EventSignup", }, }, - 'event_search_with_mueller_load_slow_api.html': { + "event_search_with_mueller_load_slow_api.html": { "SLOW_API": True, "filename": "event_search.html", "form": { @@ -814,10 +812,10 @@ def event_create(days_from_now=7, localtime=15, id=343775, "show_city": True, "show_zip": True, "show_public_description": True, - "name": "fakecampaign-mueller_load_events" + "name": "fakecampaign-mueller_load_events", }, }, - 'event_search_with_mueller_load_slow_search.html': { + "event_search_with_mueller_load_slow_search.html": { "SLOW_SEARCH": True, "filename": "event_search.html", "form": { @@ -838,21 +836,21 @@ def event_create(days_from_now=7, localtime=15, id=343775, "show_city": True, "show_zip": True, "show_public_description": True, - "name": "fakecampaign-mueller_load_events" + "name": "fakecampaign-mueller_load_events", }, }, - 'event_create.html': { + "event_create.html": { "filename": "event_create.html", - 'page': { + "page": { "title": "Event Creation - March on Washington", "canonical_url": "http://example.com/", "type": "EventCreate", }, - 'form': { - 'thank_you_text': '

Thanks!

' + "form": { + "thank_you_text": "

Thanks!

", }, - 'campaign': { - 'allow_private': True, + "campaign": { + "allow_private": True, "local_title": "Campaign Title", "use_title": True, "show_venue": True, @@ -860,42 +858,42 @@ def event_create(days_from_now=7, localtime=15, id=343775, "show_address1": True, "show_city": True, "show_zip": True, - "show_public_description": True - }, - 'event_starts_at': { - 'name': 'event_starts_at', - 'hidden_date': False, - 'static_date': False, - 'default_date': False, #could be text of date - 'hidden_time': False, - 'static_time': False, - 'default_time': '10:00', - 'default_ampm': 'AM', - }, - 'user_fields': [ - {'field_name': 'name', - 'label_text': 'Name', - 'input_tag': '', + "show_public_description": True, + }, + "event_starts_at": { + "name": "event_starts_at", + "hidden_date": False, + "static_date": False, + "default_date": False, #could be text of date + "hidden_time": False, + "static_time": False, + "default_time": "10:00", + "default_ampm": "AM", + }, + "user_fields": [ + {"field_name": "name", + "label_text": "Name", + "input_tag": '', }, - {'field_name': 'email', - 'label_text': 'Email Address', - 'input_tag': '', + {"field_name": "email", + "label_text": "Email Address", + "input_tag": '', }, - {'field_name': 'address1', - 'label_text': 'Street Address', - 'input_tag': '', + {"field_name": "address1", + "label_text": "Street Address", + "input_tag": '', }, - {'field_name': 'zip', - 'label_text': 'ZIP Code', - 'input_tag': '', + {"field_name": "zip", + "label_text": "ZIP Code", + "input_tag": '', }, - {'field_name': 'phone', - 'label_text': 'Phone', - 'input_tag': '', + {"field_name": "phone", + "label_text": "Phone", + "input_tag": '', }, ], }, - 'event_search_rapidresponse_filter.html': { + "event_search_rapidresponse_filter.html": { "filename": "event_search.html", "form": { "search_page_text": "

Search page text for campaign with only future events.

", @@ -905,10 +903,10 @@ def event_create(days_from_now=7, localtime=15, id=343775, "name": "fakecampaign-with-future-events_attend", "type": "EventSignup", "custom_fields": { - "rapid_response_active_event_start_date": rel_date(-1).strftime('%Y-%m-%d'), - "rapid_response_active_event_end_date": rel_date(3).strftime('%Y-%m-%d'), - "rapid_response_stranded_event_disclaimer": 'UNCONFIRMED event (we have not confirmed this event with the host yet)', - } + "rapid_response_active_event_start_date": rel_date(-1).strftime("%Y-%m-%d"), + "rapid_response_active_event_end_date": rel_date(3).strftime("%Y-%m-%d"), + "rapid_response_stranded_event_disclaimer": "UNCONFIRMED event (we have not confirmed this event with the host yet)", + }, }, "campaign": { "local_title": "Campaign Title for campaign with rapid-response filter", @@ -920,40 +918,40 @@ def event_create(days_from_now=7, localtime=15, id=343775, "show_zip": True, "show_public_description": True, "name": "fakecampaign-with-future-events", - "public_create_page": True + "public_create_page": True, }, "events": [event_create(1, 10, 343123), event_create(1, 15, 343124), event_create(4, 15, 343125), - event_create(0, 15, 343130, place_index=57, minutes_from_now=5) + event_create(0, 15, 343130, place_index=57, minutes_from_now=5), ], }, - 'event_create-updating': { + "event_create-updating": { "filename": "event_create.html", - 'update': True, - 'logged_in_user': { - 'akid': 34563841, - 'name': 'Stephen King', - 'first_name': 'Stephen', - 'last_name': 'King', - 'address1': 'Elm Street', - 'city': 'Denver', - 'state': 'CO', - 'zip': "80210", - }, - 'args': { - 'update': 1, - }, - 'page': { + "update": True, + "logged_in_user": { + "akid": 34563841, + "name": "Stephen King", + "first_name": "Stephen", + "last_name": "King", + "address1": "Elm Street", + "city": "Denver", + "state": "CO", + "zip": "80210", + }, + "args": { + "update": 1, + }, + "page": { "title": "Event Creation - update existing event", "type": "EventCreate", "canonical_url": "http://example.com/", - 'custom_fields': { - 'survey_always_show_user_fields': "1", - } + "custom_fields": { + "survey_always_show_user_fields": "1", + }, + }, + "form": { + "thank_you_text": "

Thanks!

", }, - 'form': { - 'thank_you_text': '

Thanks!

' - } }, } diff --git a/dsa_actionkit/contexts/lib.py b/dsa_actionkit/contexts/lib.py index 7e397c8..ef44b99 100644 --- a/dsa_actionkit/contexts/lib.py +++ b/dsa_actionkit/contexts/lib.py @@ -1,21 +1,22 @@ from django.utils.html import format_html + class user(dict): def __str__(self): - return self.get('name') + return self.get("name") def field(fielddict): - field = format_html(fielddict.get('input_tag')) - field.name = fielddict.get('field_name') - field.id_for_label = 'id_{}'.format(fielddict.get('field_name', '')) + field = format_html(fielddict.get("input_tag")) + field.name = fielddict.get("field_name") + field.id_for_label = "id_{}".format(fielddict.get("field_name", "")) field.label_tag = format_html('', field.id_for_label, - fielddict.get('label_text', '')) - field.label = fielddict.get('label_text', '') + fielddict.get("label_text", "")) + field.label = fielddict.get("label_text", "") return field - + class userform(dict): @@ -25,19 +26,19 @@ def __init__(self, maindict, formdict): class formobj(dict): def __iter__(self, source=None): if not source: - source = self.get('user_fields', []) + source = self.get("user_fields", []) return iter([field(f) for f in source]) def visible_fields(self): - return self.__iter__(self.get('visible_fields')) - + return self.__iter__(self.get("visible_fields")) + self.update({ - 'form': formobj(formdict), - 'user_fields': formdict.get('user_fields'), - 'templateset': { + "form": formobj(formdict), + "user_fields": formdict.get("user_fields"), + "templateset": { "lang": { - "country_names_us_first": [(c,c) for c in country_list] - } + "country_names_us_first": [(c,c) for c in country_list], + }, }, }) @@ -355,6 +356,6 @@ def states(): ] def countries(): - return ''.join([ - '' % {'c': c} + return "".join([ + '' % {"c": c} for c in country_list]) diff --git a/dsa_actionkit/contexts/page_contexts.py b/dsa_actionkit/contexts/page_contexts.py index f7eea76..a94d303 100644 --- a/dsa_actionkit/contexts/page_contexts.py +++ b/dsa_actionkit/contexts/page_contexts.py @@ -1,29 +1,26 @@ -from . import account_contexts -from . import donation_contexts -from . import event_contexts -from . import survey_contexts +from . import account_contexts, donation_contexts, event_contexts, survey_contexts contexts = { - 'base': { - 'thanks.html': { - 'filename': 'thanks.html', - 'page': { + "base": { + "thanks.html": { + "filename": "thanks.html", + "page": { "title": "Thanks, you are the best", - "canonical_url": "http://example.com/" + "canonical_url": "http://example.com/", }, - 'form': { - 'thank_you_text': '

Thanks!

' - } + "form": { + "thank_you_text": "

Thanks!

", + }, + }, + "logout.html": { + "filename": "logout.html", }, - 'logout.html': { - 'filename': 'logout.html' - } - } + }, #kinda silly, but avoid appending to the bottom because then git merge conflicts arise more often. #let's do the context values in alphabetical order. } -contexts.update({'donations': donation_contexts.contexts}) -contexts.update({'events': event_contexts.contexts}) -contexts.update({'accounts': account_contexts.contexts}) -contexts.update({'surveys': survey_contexts.contexts}) +contexts.update({"donations": donation_contexts.contexts}) +contexts.update({"events": event_contexts.contexts}) +contexts.update({"accounts": account_contexts.contexts}) +contexts.update({"surveys": survey_contexts.contexts}) diff --git a/dsa_actionkit/contexts/survey_contexts.py b/dsa_actionkit/contexts/survey_contexts.py index fe5e5f8..fe6ac94 100644 --- a/dsa_actionkit/contexts/survey_contexts.py +++ b/dsa_actionkit/contexts/survey_contexts.py @@ -1,22 +1,22 @@ from django.utils.html import format_html logged_in_data_with_hide_recognized_block = { - 'filename': 'survey.html', - 'page': { + "filename": "survey.html", + "page": { "title": "Survey page (stub)", "canonical_url": "http://example.com/survey/foobar", "custom_fields": { "layout_options": "hide_recognized_block", }, }, - 'form': { - 'introduction_text': 'Take our Survey!', - 'surveyquestion_set': { - 'all': [ - {'question_label': "How do you feel?", - 'question_html': '', - 'input_html': format_html(''), - 'placeholder': 'Share your feelings', + "form": { + "introduction_text": "Take our Survey!", + "surveyquestion_set": { + "all": [ + {"question_label": "How do you feel?", + "question_html": '', + "input_html": format_html(''), + "placeholder": "Share your feelings", }, ], }, @@ -28,89 +28,89 @@ "first_name": "Morticia", "last_name": "Addams", }, - 'user_fields': [ - {'field_name': 'name', - 'label_text': 'Name', - 'input_tag': '', - 'input_html': format_html(''), + "user_fields": [ + {"field_name": "name", + "label_text": "Name", + "input_tag": '', + "input_html": format_html(''), }, - {'field_name': 'email', - 'label_text': 'Email Address', - 'input_tag': '', - 'input_html': format_html(''), + {"field_name": "email", + "label_text": "Email Address", + "input_tag": '', + "input_html": format_html(''), }, - {'field_name': 'address1', - 'label_text': 'Street Address', - 'input_tag': '', - 'input_html': format_html(''), + {"field_name": "address1", + "label_text": "Street Address", + "input_tag": '', + "input_html": format_html(''), }, - {'field_name': 'city', - 'label_text': 'City', - 'input_tag': '', - 'input_html': format_html(''), + {"field_name": "city", + "label_text": "City", + "input_tag": '', + "input_html": format_html(''), }, - {'field_name': 'state', - 'label_text': 'State', - 'input_tag': '', - 'input_html': format_html(''), + {"field_name": "state", + "label_text": "State", + "input_tag": '', + "input_html": format_html(''), }, - {'field_name': 'zip', - 'label_text': 'ZIP Code', - 'input_tag': '', - 'input_html': format_html(''), + {"field_name": "zip", + "label_text": "ZIP Code", + "input_tag": '', + "input_html": format_html(''), }, - {'field_name': 'phone', - 'label_text': 'Phone', - 'input_tag': '', - 'input_html': format_html(''), + {"field_name": "phone", + "label_text": "Phone", + "input_tag": '', + "input_html": format_html(''), }, ], } no_questions = { - 'filename': 'survey.html', - 'page': { + "filename": "survey.html", + "page": { "title": "Survey page (stub)", - "canonical_url": "http://example.com/survey/foobar" + "canonical_url": "http://example.com/survey/foobar", }, - 'form': { - 'introduction_text': 'Take our Survey!', - 'surveyquestion_set': { - 'all': [], + "form": { + "introduction_text": "Take our Survey!", + "surveyquestion_set": { + "all": [], }, }, - 'user_fields': [ - {'field_name': 'name', - 'label_text': 'Name', - 'input_tag': '', - 'input_html': format_html(''), + "user_fields": [ + {"field_name": "name", + "label_text": "Name", + "input_tag": '', + "input_html": format_html(''), }, - {'field_name': 'email', - 'label_text': 'Email Address', - 'input_tag': '', - 'input_html': format_html(''), + {"field_name": "email", + "label_text": "Email Address", + "input_tag": '', + "input_html": format_html(''), }, - {'field_name': 'address1', - 'label_text': 'Street Address', - 'input_tag': '', - 'input_html': format_html(''), + {"field_name": "address1", + "label_text": "Street Address", + "input_tag": '', + "input_html": format_html(''), }, - {'field_name': 'zip', - 'label_text': 'ZIP Code', - 'input_tag': '', - 'input_html': format_html(''), + {"field_name": "zip", + "label_text": "ZIP Code", + "input_tag": '', + "input_html": format_html(''), }, - {'field_name': 'phone', - 'label_text': 'Phone', - 'input_tag': '', - 'input_html': format_html(''), + {"field_name": "phone", + "label_text": "Phone", + "input_tag": '', + "input_html": format_html(''), }, ], } no_survey = { - 'filename': 'survey.html', - 'page': { + "filename": "survey.html", + "page": { "title": "Survey page (stub)", "canonical_url": "http://example.com/survey/foobar", "custom_fields": { @@ -120,127 +120,127 @@ } survey = { - 'filename': 'survey.html', - 'page': { + "filename": "survey.html", + "page": { "title": "Survey page (stub)", - "canonical_url": "http://example.com/survey/foobar" + "canonical_url": "http://example.com/survey/foobar", }, - 'form': { - 'introduction_text': 'Take our Survey!', - 'surveyquestion_set': { - 'all': [ - {'question_label': "How do you feel?", - 'question_html': '', - 'input_html': format_html(''), - 'placeholder': 'Share your feelings', + "form": { + "introduction_text": "Take our Survey!", + "surveyquestion_set": { + "all": [ + {"question_label": "How do you feel?", + "question_html": '', + "input_html": format_html(''), + "placeholder": "Share your feelings", }, ], }, }, - 'user_fields': [ - {'field_name': 'name', - 'label_text': 'Name', - 'input_tag': '', - 'input_html': format_html(''), + "user_fields": [ + {"field_name": "name", + "label_text": "Name", + "input_tag": '', + "input_html": format_html(''), }, - {'field_name': 'email', - 'label_text': 'Email Address', - 'input_tag': '', - 'input_html': format_html(''), + {"field_name": "email", + "label_text": "Email Address", + "input_tag": '', + "input_html": format_html(''), }, - {'field_name': 'address1', - 'label_text': 'Street Address', - 'input_tag': '', - 'input_html': format_html(''), + {"field_name": "address1", + "label_text": "Street Address", + "input_tag": '', + "input_html": format_html(''), }, - {'field_name': 'city', - 'label_text': 'City', - 'input_tag': '', - 'input_html': format_html(''), + {"field_name": "city", + "label_text": "City", + "input_tag": '', + "input_html": format_html(''), }, - {'field_name': 'state', - 'label_text': 'State', - 'input_tag': '', - 'input_html': format_html(''), + {"field_name": "state", + "label_text": "State", + "input_tag": '', + "input_html": format_html(''), }, - {'field_name': 'zip', - 'label_text': 'ZIP Code', - 'input_tag': '', - 'input_html': format_html(''), + {"field_name": "zip", + "label_text": "ZIP Code", + "input_tag": '', + "input_html": format_html(''), }, - {'field_name': 'phone', - 'label_text': 'Phone', - 'input_tag': '', - 'input_html': format_html(''), + {"field_name": "phone", + "label_text": "Phone", + "input_tag": '', + "input_html": format_html(''), }, ], } shipping_survey = { - 'filename': 'survey.html', - 'page': { + "filename": "survey.html", + "page": { "title": "Shipping survey", - "canonical_url": "http://example.com/survey/foobar" + "canonical_url": "http://example.com/survey/foobar", }, - 'form': { - 'introduction_text': 'verify shipping!', - 'surveyquestion_set': { - 'all': [ - {'question_label': "How do you feel?", - 'question_html': '', - 'input_html': format_html(''), - 'placeholder': 'Share your feelings', - 'field_name': 'howfeel', + "form": { + "introduction_text": "verify shipping!", + "surveyquestion_set": { + "all": [ + {"question_label": "How do you feel?", + "question_html": '', + "input_html": format_html(''), + "placeholder": "Share your feelings", + "field_name": "howfeel", }, - {'question_label': "Address", - 'question_html': '', - 'input_html': format_html(''), - 'field_name': 'shipping_address', + {"question_label": "Address", + "question_html": '', + "input_html": format_html(''), + "field_name": "shipping_address", }, - {'question_label': "Address Line 2", - 'question_html': '', - 'input_html': format_html(''), - 'field_name': 'shipping_address2', + {"question_label": "Address Line 2", + "question_html": '', + "input_html": format_html(''), + "field_name": "shipping_address2", }, - {'question_label': "City", - 'question_html': '', - 'input_html': format_html(''), - 'field_name': 'shipping_city', + {"question_label": "City", + "question_html": '', + "input_html": format_html(''), + "field_name": "shipping_city", }, - {'question_label': "zip", - 'question_html': '', - 'input_html': format_html(''), - 'placeholder': 'Share your feelings', - 'field_name': 'shipping_zip', + {"question_label": "zip", + "question_html": '', + "input_html": format_html(''), + "placeholder": "Share your feelings", + "field_name": "shipping_zip", }, ], }, }, - 'user_fields': [ - {'field_name': 'name', - 'label_text': 'Name', - 'input_tag': '', - 'input_html': format_html(''), + "user_fields": [ + {"field_name": "name", + "label_text": "Name", + "input_tag": '', + "input_html": format_html(''), }, - {'field_name': 'email', - 'label_text': 'Email Address', - 'input_tag': '', - 'input_html': format_html(''), + {"field_name": "email", + "label_text": "Email Address", + "input_tag": '', + "input_html": format_html(''), }, - {'field_name': 'address1', - 'label_text': 'Street Address', - 'input_tag': '', - 'input_html': format_html(''), + {"field_name": "address1", + "label_text": "Street Address", + "input_tag": '', + "input_html": format_html(''), }, - {'field_name': 'zip', - 'label_text': 'ZIP Code', - 'input_tag': '', - 'input_html': format_html(''), + {"field_name": "zip", + "label_text": "ZIP Code", + "input_tag": '', + "input_html": format_html(''), }, - {'field_name': 'phone', - 'label_text': 'Phone', - 'input_tag': '', - 'input_html': format_html(''), + {"field_name": "phone", + "label_text": "Phone", + "input_tag": '', + "input_html": format_html(''), }, ], } @@ -252,35 +252,35 @@ "name": "Morticia Addams", "first_name": "Morticia", "last_name": "Addams", - } + }, } logged_in_data.update(survey) letter_to_congress_base = { - 'filename': 'letter.html', - 'page': { - 'title': 'Tell Letter to Congress', - 'goal': '100', - 'custom_fields': { - 'layout_options': 'lost_pages_redesign' - } + "filename": "letter.html", + "page": { + "title": "Tell Letter to Congress", + "goal": "100", + "custom_fields": { + "layout_options": "lost_pages_redesign", + }, }, - 'form': { - 'statement_leadin': '

Hello, please sign our letter to congress for this very-good-cause.

', - 'letter_text': 'Dear Senator,\n\nPlease listen to us?\nThis is very important.\nPlease listen to us?\nThis is very important.\nPlease listen to us?\nThis is very important.\nPlease listen to us?\nThis is very important.\nPlease listen to us?\nThis is very important.\nPlease listen to us?\nThis is very important.\nPlease listen to us?\nThis is very important.\nPlease listen to us?\nThis is very important.\nPlease listen to us?\nThis is very important.\nPlease listen to us?\nThis is very important.\nPlease listen to us?\nThis is very important.\nPlease listen to us?\nThis is very important.\nPlease listen to us?\nThis is very important.\nPlease listen to us?\nThis is very important.\nPlease listen to us?\nThis is very important.\nPlease listen to us?\nThis is very important.\nPlease listen to us?\nThis is very important.\nPlease listen to us?\nThis is very important.\nPlease listen to us?\nThis is very important.\nPlease listen to us?\nThis is very important.\nPlease listen to us?\nThis is very important.\nPlease listen to us?\nThis is very important.\nPlease listen to us?\nThis is very important.\nPlease listen to us?\nThis is very important.\nPlease listen to us?\nThis is very important.\nPlease listen to us?\nThis is very important.\nPlease listen to us?\nThis is very important.\nPlease listen to us?\nThis is very important.\nPlease listen to us?\nThis is very important.\nPlease listen to us?\nThis is very important.\nPlease listen to us?\nThis is very important.\nPlease listen to us?\nThis is very important.\nPlease listen to us?\nThis is very important.\nPlease listen to us?\nThis is very important.\nPlease listen to us?\nThis is very important.\nPlease listen to us?\nThis is very important.\nPlease listen to us?\nThis is very important.\nPlease listen to us?\nThis is very important.\nPlease listen to us?\nThis is very important.\nPlease listen to us?\nThis is very important.\nPlease listen to us?\nThis is very important.\nPlease listen to us?\nThis is very important.\nPlease listen to us?\nThis is very important.\nPlease listen to us?\nThis is very important.\nPlease listen to us?\nThis is very important.\nPlease listen to us?\nThis is very important.\nPlease listen to us?\nThis is very important.\nPlease listen to us?\nThis is very important.\nPlease listen to us?\nThis is very important.\nPlease listen to us?\nThis is very important.\nPlease listen to us?\nThis is very important.\nPlease listen to us?\nThis is very important.\nPlease listen to us?\nThis is very important.\nPlease listen to us?\nThis is very important.\nPlease listen to us?\nThis is very important.', - 'about_text': 'This is what this thing is all about.', + "form": { + "statement_leadin": "

Hello, please sign our letter to congress for this very-good-cause.

", + "letter_text": "Dear Senator,\n\nPlease listen to us?\nThis is very important.\nPlease listen to us?\nThis is very important.\nPlease listen to us?\nThis is very important.\nPlease listen to us?\nThis is very important.\nPlease listen to us?\nThis is very important.\nPlease listen to us?\nThis is very important.\nPlease listen to us?\nThis is very important.\nPlease listen to us?\nThis is very important.\nPlease listen to us?\nThis is very important.\nPlease listen to us?\nThis is very important.\nPlease listen to us?\nThis is very important.\nPlease listen to us?\nThis is very important.\nPlease listen to us?\nThis is very important.\nPlease listen to us?\nThis is very important.\nPlease listen to us?\nThis is very important.\nPlease listen to us?\nThis is very important.\nPlease listen to us?\nThis is very important.\nPlease listen to us?\nThis is very important.\nPlease listen to us?\nThis is very important.\nPlease listen to us?\nThis is very important.\nPlease listen to us?\nThis is very important.\nPlease listen to us?\nThis is very important.\nPlease listen to us?\nThis is very important.\nPlease listen to us?\nThis is very important.\nPlease listen to us?\nThis is very important.\nPlease listen to us?\nThis is very important.\nPlease listen to us?\nThis is very important.\nPlease listen to us?\nThis is very important.\nPlease listen to us?\nThis is very important.\nPlease listen to us?\nThis is very important.\nPlease listen to us?\nThis is very important.\nPlease listen to us?\nThis is very important.\nPlease listen to us?\nThis is very important.\nPlease listen to us?\nThis is very important.\nPlease listen to us?\nThis is very important.\nPlease listen to us?\nThis is very important.\nPlease listen to us?\nThis is very important.\nPlease listen to us?\nThis is very important.\nPlease listen to us?\nThis is very important.\nPlease listen to us?\nThis is very important.\nPlease listen to us?\nThis is very important.\nPlease listen to us?\nThis is very important.\nPlease listen to us?\nThis is very important.\nPlease listen to us?\nThis is very important.\nPlease listen to us?\nThis is very important.\nPlease listen to us?\nThis is very important.\nPlease listen to us?\nThis is very important.\nPlease listen to us?\nThis is very important.\nPlease listen to us?\nThis is very important.\nPlease listen to us?\nThis is very important.\nPlease listen to us?\nThis is very important.\nPlease listen to us?\nThis is very important.\nPlease listen to us?\nThis is very important.\nPlease listen to us?\nThis is very important.\nPlease listen to us?\nThis is very important.", + "about_text": "This is what this thing is all about.", }, - 'progress': { - 'goal': 100, - 'current': 90, - 'total': { - 'actions': 90 + "progress": { + "goal": 100, + "current": 90, + "total": { + "actions": 90, }, - 'goal_type': 'actions' + "goal_type": "actions", }, - 'context': { + "context": { "progress": {"total": {"actions": 1}, "goal": 5, "goal_type": "actions", "recent": {"actions": 1}, "time": 1621261302.6000607, "age": 447.172566652298}, - } + }, } letter_to_congress = {} letter_to_congress_login = {} @@ -291,14 +291,14 @@ letter_to_congress_login.update(letter_to_congress_base) contexts = { - 'survey.html': survey, - 'shipping_survey.html': shipping_survey, - 'survey_logged_in': logged_in_data, - 'survey_logged_in_hide_recognized': logged_in_data_with_hide_recognized_block, - 'survey_no_questions': no_questions, - 'survey_no_survey': no_survey, - 'letter.html': letter_to_congress, - 'letter_logged_in': letter_to_congress_login, + "survey.html": survey, + "shipping_survey.html": shipping_survey, + "survey_logged_in": logged_in_data, + "survey_logged_in_hide_recognized": logged_in_data_with_hide_recognized_block, + "survey_no_questions": no_questions, + "survey_no_survey": no_survey, + "letter.html": letter_to_congress, + "letter_logged_in": letter_to_congress_login, #kinda silly, but avoid appending to the bottom because then git merge conflicts arise more often. #let's do the context values in alphabetical order. } diff --git a/dsa_actionkit/moveon_fakeapi.py b/dsa_actionkit/moveon_fakeapi.py index 1c64a7d..92c9af6 100644 --- a/dsa_actionkit/moveon_fakeapi.py +++ b/dsa_actionkit/moveon_fakeapi.py @@ -2,18 +2,18 @@ def mo_event_data(event): - eobj = event.get('obj') + eobj = event.get("obj") machine_offset = time.time() - time.mktime(time.gmtime()) # correction factor for when this runs on machines that aren't defaulting to UTC - naive_start_time = int(time.mktime(eobj['starts_at_utc'].timetuple())) + naive_start_time = int(time.mktime(eobj["starts_at_utc"].timetuple())) starts_utc = naive_start_time + machine_offset - timezone_offset = (int(time.mktime(eobj['starts_at'].timetuple())) - naive_start_time) / 3600 - full = 0 if not event['max_attendees'] else int(bool(event['max_attendees'] <= event['attendee_count'])) - return {'lat': float(event['latitude']), - 'lng': float(event['longitude']), - 'id': event['id'], - 'utc': starts_utc, - 'tzo': timezone_offset, - 'f': full, + timezone_offset = (int(time.mktime(eobj["starts_at"].timetuple())) - naive_start_time) / 3600 + full = 0 if not event["max_attendees"] else int(bool(event["max_attendees"] <= event["attendee_count"])) + return {"lat": float(event["latitude"]), + "lng": float(event["longitude"]), + "id": event["id"], + "utc": starts_utc, + "tzo": timezone_offset, + "f": full, # this is not a perfect reflection of the api, but we are lazy so we send titles with the main batch - 'city_etc': '{}, {}'.format(event['city'], event['state']), - 'title': event['title']} + "city_etc": "{}, {}".format(event["city"], event["state"]), + "title": event["title"]} diff --git a/dsa_actionkit/settings.py b/dsa_actionkit/settings.py index a48e416..7be57fa 100644 --- a/dsa_actionkit/settings.py +++ b/dsa_actionkit/settings.py @@ -1,71 +1,40 @@ -import json +import contextlib import os -import time - -try: - from urlparse import urlparse -except ImportError: - # python3 - from urllib.parse import urlparse - -from django.urls import re_path -from django.conf.urls.static import static -from django.http import Http404, HttpResponse -from django.shortcuts import redirect, render -from django.template.loader import render_to_string -from django.views.static import serve - -from .moveon_fakeapi import mo_event_data - -""" -try running with -aktemplates runserver 0.0.0.0:1234 -""" +from pathlib import Path DEBUG = True -SECRET_KEY = 'who cares!' -INSTALLED_APPS = ['dsa_actionkit', ] -try: - INSTALLED_APPS.append('django_extensions') -except: - pass - -#one directory down -APP_PATH = os.path.dirname(__file__) -PROJECT_ROOT_PATH = os.path.abspath(os.getcwd()) - -############# -# STATIC DIRECTORY -############# - -#note this only works if DEBUG=True -STATIC_ROOT = os.environ.get('STATIC_ROOT', os.path.join(PROJECT_ROOT_PATH, './static')) -STATIC_URL = os.environ.get('STATIC_URL', '/static/') -STATIC_FALLBACK = os.environ.get('STATIC_FALLBACK', False) -STATIC_LOCAL = os.environ.get('STATIC_URL', None) # an explicit local or not - -############# -# TEMPLATES -############# -DEFAULT_TEMPLATES = os.path.join(APP_PATH, 'templates') +SECRET_KEY = os.environ["DJANGO_SECRET_KEY"] +INSTALLED_APPS = ["dsa_actionkit" ] +with contextlib.suppress(Exception): + INSTALLED_APPS.append("django_extensions") + +ROOT_URLCONF = "dsa_actionkit.urls" +APP_PATH = Path().parent +PROJECT_ROOT_PATH = Path.resolve(Path.cwd()) + +STATIC_ROOT = os.environ.get("STATIC_ROOT", PROJECT_ROOT_PATH / "static") +STATIC_URL = os.environ.get("STATIC_URL", "/static/") +STATIC_FALLBACK = os.environ.get("STATIC_FALLBACK", False) +STATIC_LOCAL = os.environ.get("STATIC_URL", None) +DEFAULT_TEMPLATES = APP_PATH / "templates" DIR_TEMPLATES = [] -if os.environ.get('TEMPLATE_DIR'): - DIR_TEMPLATES.append(os.environ.get('TEMPLATE_DIR')) +if os.environ.get("TEMPLATE_DIR"): + DIR_TEMPLATES.append(os.environ.get("TEMPLATE_DIR")) else: - for d in ('template_set/', '_layouts/', '_includes/'): - dd = os.path.join(PROJECT_ROOT_PATH, d) - if os.path.exists(dd): + for d in ("template_set/", "_layouts/", "_includes/"): + dd = PROJECT_ROOT_PATH / d + if Path.exists(dd): DIR_TEMPLATES.append(dd) DIR_TEMPLATES.append(DEFAULT_TEMPLATES) TEMPLATES = [ { - 'BACKEND': 'django.template.backends.django.DjangoTemplates', - 'DIRS': DIR_TEMPLATES, - 'APP_DIRS': True, - 'OPTIONS': { - 'builtins': ['dsa_actionkit.templatetags.actionkit_tags'], + "BACKEND": "django.template.backends.django.DjangoTemplates", + "DIRS": DIR_TEMPLATES, + "APP_DIRS": True, + "OPTIONS": { + "builtins": ["dsa_actionkit.templatetags.actionkit_tags"], }, }, ] @@ -73,172 +42,9 @@ MIDDLEWARE_CLASSES = [] -def _get_context_data(request, name=None, page=None, use_referer=False): - from dsa_actionkit.contexts.page_contexts import contexts - port = '4000' - hostport = request.get_host().split(':') - if len(hostport) > 1: - port = hostport[1] - - if use_referer: - paths = None - if request.META.get('HTTP_REFERER'): - paths = urlparse(request.META['HTTP_REFERER']).path.split('/') - elif request.GET.get('path'): - # e.g. &path=/events/event_search.html - paths = request.GET['path'].split('/') - if paths and len(paths) > 1: - name = paths[1] - if len(paths) > 2: - page = paths[2] - - custom_contexts_file = os.path.join(PROJECT_ROOT_PATH, - os.environ.get('CUSTOM_CONTEXTS', 'contexts.json')) - if os.path.exists(custom_contexts_file): - try: - contexts.update({'Custom': json.loads(open(custom_contexts_file).read())}) - except ValueError as e: - raise Exception("JSON Parsing Error for context file %s %s" % ( - custom_contexts_file, e.message)) - #first use ?template= if there, otherwise name's template, otherwise homepage - cxt = dict( - devenv={ - 'enabled': True, - 'port': port, - 'STATIC_URL': STATIC_URL, - 'STATIC_LOCAL': STATIC_LOCAL, - 'MO_EVENTS_API': '/fake/api/events' - } - ) - context_data = contexts.get(name, {}) - if page: - context_data = contexts.get(name, {}).get(page, {}) - cxt.update(context_data) - if not context_data: - sections = [] - for section, pages in sorted(contexts.items()): - sections.append([section, sorted(pages.items())]) - cxt.update({ - 'page': {'title':'Homepage'}, - 'pagelinks': sections}) - if request.GET.get('user_id'): - #for debugging tests based on user.id % 2, e.g. - context_data.setdefault('user', {}).update({'id': int(request.GET.get('user_id'))}) - args = cxt.get('args', {}).copy() - args.update(request.GET.dict()) - cxt['args'] = args - if 'akid' not in cxt: - cxt['akid'] = cxt['args'].get('akid') - cxt['request'] = request - cxt['js_context'] = '""' # FUTURE: what should go in here? - return cxt - -############# -# HOME PAGE TEST -############# - -def index(request, name=None, page=None): - cxt = _get_context_data(request, name, page) - template = request.GET.get('template', - cxt.get('filename', "homepagetest.html")) - - return render(request, template, cxt) - -def login_context(request): - cxt = _get_context_data(request, use_referer=True) - from dsa_actionkit.contexts.event_context_json import event_json - event_json_copy = event_json.copy() - coming_from = request.GET.get('url','') - if 'event' in coming_from \ - or 'logged_in' in coming_from \ - or 'survey_logged_in' in coming_from: - if not request.GET.get('login') and 'survey_logged_in' not in coming_from: - del event_json_copy['name'] - return HttpResponse( - 'actionkit.forms.onContextLoaded(%s)' % json.dumps(event_json_copy)) - elif cxt.get('context'): - return HttpResponse('actionkit.forms.onContextLoaded(%s)' % json.dumps(cxt['context'])) - else: - return HttpResponse( - #text key has all the generic error messages - 'actionkit.forms.onContextLoaded({"text": %s})' % json.dumps(event_json['text'])) - -def user_password_forgot(request): - return HttpResponse('unimplemented') - -def logout(request): - if request.GET.get('next'): - return redirect(request.GET.get('next')) - return redirect('/logout.html') - -def event_search_results(request, page): - cxt = _get_context_data(request, 'events', 'WILL_USE_REFERER_HEADER', use_referer=True) - # special query results context: - all = cxt['args'].get('all') == '1' - cxt.update({'all': all}) - if cxt.get('SLOW_SEARCH'): - # This allows us to test for race conditions - time.sleep(2) - search_results = render_to_string('event_search_results.html', cxt) - return HttpResponse('actionkit.forms.onEventSearchResults({})' - .format(json.dumps(search_results))) - -def event_api_moveon_fake(request): - """Fake representation of MoveOn events api""" - cxt = _get_context_data(request, 'events', 'WILL_USE_REFERER_HEADER', use_referer=True) - events = cxt.get('events', []) - if cxt.get('SLOW_API'): - # This allows us to test for race conditions - time.sleep(2) - if cxt.get('500_API'): - raise Exception('Cause failure to allow graceful degradation') - search_results = [mo_event_data(evt) for evt in events] - return HttpResponse(json.dumps({'events': search_results}), content_type='application/json') - -def proxy_serve(request, path, document_root=None, show_indexes=False): - try_proxy = True - try: - import requests - except ImportError: - try_proxy = False - try: - return serve(request, path, document_root, show_indexes) - except Http404: - if try_proxy: - prefix = request.path.split('/')[1] - content = requests.get('https://roboticdogs.actionkit.com/{}/{}'.format(prefix, path), verify=False) - if content.status_code == 200: - return HttpResponse(content.content, content_type=content.headers['Content-Type']) - raise Http404 - - -############# -# URLS -############# - -ROOT_URLCONF = 'dsa_actionkit.settings' - -urlpatterns = [ - re_path(r'^context', login_context), - re_path(r'^progress', login_context, name='progress'), - re_path(r'^logout', logout, name="logout"), - re_path(r'^(?P[-.\w]+)?(/(?P[-.\w]+))?$', index), - re_path(r'^forgot/$', user_password_forgot, name='user_password_forgot'), - re_path(r'^cms/event/(?P[-.\w]+)/search_results/', event_search_results, name='event_search_results'), - re_path(r'^fake/api/events', event_api_moveon_fake, name="event_api_moveon_fake"), - # ActionKit urls or {% url %} template tag: - re_path(r'^fake/stub/reverse', event_api_moveon_fake, name="reverse_donation"), -] -if STATIC_ROOT: - urlpatterns = (urlpatterns - + static(STATIC_URL, document_root=STATIC_ROOT) - + static('/resources/', - view=proxy_serve, - document_root=os.path.join(STATIC_ROOT, './resources')) - + static('/media/', - view=proxy_serve, - document_root=os.path.join(STATIC_ROOT, './media')) - ) - -if os.path.exists(os.path.join(PROJECT_ROOT_PATH, 'local_settings.py')): - from local_settings import * +DATABASES = { + "default": { + "ENGINE": "django.db.backends.sqlite3", + "NAME": "db.sqlite", + }, +} diff --git a/dsa_actionkit/templatetags/actionkit_tags.py b/dsa_actionkit/templatetags/actionkit_tags.py index 01f5c29..80fe111 100644 --- a/dsa_actionkit/templatetags/actionkit_tags.py +++ b/dsa_actionkit/templatetags/actionkit_tags.py @@ -1,6 +1,6 @@ import datetime -import os import re + from django.conf import settings from django.template import Library, Node, Variable from django.template.defaultfilters import safe @@ -23,7 +23,7 @@ class NoContentNode(Node): def render(self, context): - return '' + return "" class StaticContentNode(Node): def __init__(self, staticcontent): @@ -43,7 +43,7 @@ def render(self, context): self.rendered = True return self.nodelist.render(context) else: - return '' + return "" class SetVarNode(Node): @@ -53,7 +53,7 @@ def __init__ (self, var_name, var_value): def render(self, context): context[self.name] = self.value - return '' + return "" class RecordNode(Node): @@ -68,25 +68,23 @@ def render(self, context): context[self.ary] = [] item = self.item.resolve(context) if self.reportresult: - found = re.search(r'\d+', str(item)) + found = re.search(r"\d+", str(item)) if found: item = int(found.group(1)) ary.append(item) - return '' + return "" @register.tag def once(parser, token): + """Use the tag once to wrap template code that will only be rendered one time. """ - Use the tag once to wrap template code that will only be rendered one time. - """ - nodelist = parser.parse(('endonce',)) + nodelist = parser.parse(("endonce",)) parser.delete_first_token() return OnceNode(nodelist) @register.tag def record(parser, token): - """ - https://roboticdogs.actionkit.com/docs/manual/guide/customtags.html#record + """https://roboticdogs.actionkit.com/docs/manual/guide/customtags.html#record {% with "[ ]"|load_json as user_quiz_score %} {% for field in action.custom_fields %} {% if field == [THE RIGHT ANSWER FOR THIS QUESTION] %} @@ -98,7 +96,7 @@ def record(parser, token): """ reportresult = False tokens = token.split_contents() - if tokens[0] == 'reportresult': + if tokens[0] == "reportresult": reportresult = True tokens = tokens[1:] return RecordNode(item=tokens[1], ary=tokens[3], reportresult=reportresult) @@ -108,77 +106,75 @@ def remember(parser, token): return SetVarNode(tokens[3],tokens[1]) @register.tag def right_now(parser, token): - """ - The tag right_now creates the variable {{ now }} + """The tag right_now creates the variable {{ now }} that contains the Python datetime object datetime.now(). """ return SetVarNode("now", datetime.datetime.now(timezone.utc)) @register.simple_tag def client_name(): - return getattr(settings, 'AK_CLIENT_NAME', '--AK ClientName--') + return getattr(settings, "AK_CLIENT_NAME", "--AK ClientName--") @register.simple_tag def facebook_app(): - return getattr(settings, 'AK_FACEBOOK_APP', '--facebook appid!--') + return getattr(settings, "AK_FACEBOOK_APP", "--facebook appid!--") @register.simple_tag def client_domain(): - return getattr(settings, 'AK_CLIENT_DOMAIN', 'roboticdogs.actionkit.com') + return getattr(settings, "AK_CLIENT_DOMAIN", "roboticdogs.actionkit.com") @register.simple_tag def include_tmpl(field, *args): - return safe('%s' % field) + return safe("%s" % field) @register.simple_tag def load_ak_context(somestring, *args, **kwargs): - return '' + return "" @register.simple_tag def load_prefill(*args, **kwargs): - return '' + return "" @register.simple_tag def braintree_js_libs(): - return ''' + return """ - ''' + """ @register.simple_tag def authnet_js_libs(): - return ''' + return """ - ''' + """ @register.tag def field_order(parser, token): - "takes a set of fields and sets the order for the form" + "Takes a set of fields and sets the order for the form" return NoContentNode() @register.tag def hide_by_default(parser, token): - "seems to take a field list and default-hides them" + "Seems to take a field list and default-hides them" return NoContentNode() def _add_domain(path): - fallback = getattr(settings, 'STATIC_FALLBACK', False) - filename = path.rsplit('/', 1)[1] + fallback = getattr(settings, "STATIC_FALLBACK", False) + filename = path.rsplit("/", 1)[1] if fallback: - return '%s/%s' % (fallback, filename) - elif path.startswith('//') or path.startswith('http'): + return "%s/%s" % (fallback, filename) + elif path.startswith("//") or path.startswith("http"): return path - return 'https://%s%s' % (client_domain(), path) + return "https://%s%s" % (client_domain(), path) @register.tag def load_css(parser, token): - """ - Return an absolute + """Return an absolute for each non-empty line in the block, e.g. {% load_css %} @@ -196,11 +192,10 @@ def load_css(parser, token): """ - - nodelist = parser.parse(('end',)) + nodelist = parser.parse(("end",)) parser.delete_first_token() source = nodelist[0].s - parsed = ''.join([ + parsed = "".join([ """""" % _add_domain(s.strip()) for s in source.strip().splitlines() if s and s.strip() @@ -209,18 +204,18 @@ def load_css(parser, token): @register.tag def load_js(parser, token): - nodelist = parser.parse(('end',)) + nodelist = parser.parse(("end",)) parser.delete_first_token() source = nodelist[0].s - parsed = ''.join([""" + parsed = "".join([""" """ % _add_domain(s) - for s in re.findall(r'[^\s]+js', source)]) + for s in re.findall(r"[^\s]+js", source)]) return StaticContentNode(parsed) @register.filter -def split(value, arg=' '): +def split(value, arg=" "): return value.split(arg) @register.filter @@ -261,10 +256,10 @@ def subtract(value, arg): def date_add(value, arg): # https://roboticdogs.actionkit.com/docs/manual/guide/customtags.html#date-add kwargs = {} - args = arg.split(' ') + args = arg.split(" ") for a in args: - if '=' in a: - k, val = a.split('=') + if "=" in a: + k, val = a.split("=") if k and val: kwargs[k] = int(val) return value + datetime.timedelta(**kwargs) @@ -277,23 +272,23 @@ def multiply(value, arg): @register.filter def percent_of(value, arg): - return '%.1f' % (100 * (float(value) / float(arg))) + return "%.1f" % (100 * (float(value) / float(arg))) @register.simple_tag def authnet_js_libs(): - return '' + return "" @register.simple_tag def braintree_js_libs(): - return '' + return "" @register.simple_tag -def client_domain_url(path=''): - return '%s/%s' % (client_domain(), path) +def client_domain_url(path=""): + return "%s/%s" % (client_domain(), path) @register.simple_tag def divide(top, bottom, precision): - return '%.{}f'.format(precision) % (float(top)/float(bottom)) + return f"%.{precision}f" % (float(top)/float(bottom)) @register.filter def escapeall(value): @@ -311,36 +306,35 @@ def load_json(value): @register.filter def ak_field_label(value, arg): - return '%s|%s|' % (arg, value) + return "%s|%s|" % (arg, value) @register.filter def tag_links(value, arg): - """ - {% filter referring_akid:akid|tag_links:"source=taf" %}{% include_tmpl page.followup.taf_body escaped %}{% endfilter %} + """{% filter referring_akid:akid|tag_links:"source=taf" %}{% include_tmpl page.followup.taf_body escaped %}{% endfilter %} """ # this hackily doesn't try to do good things with a pre-existing "?" in the url - return re.sub(r'(https?://[^"\'() ]+)', '\\1?%s' % arg, value) + return re.sub(r'(https?://[^"\'() ]+)', "\\1?%s" % arg, value) @register.filter def commify(value): - "add commas for numeric values" + "Add commas for numeric values" try: return format(int(value), ",d") except ValueError: if isinstance(value, float): value = str(value) - parts = value.split('.') - return '{}.{}'.format(format(int(parts[0]), ",d"), parts[1]) + parts = value.split(".") + return "{}.{}".format(format(int(parts[0]), ",d"), parts[1]) @register.filter def concatenate(value, arg): - "add commas for numeric values" - return '{}{}'.format(value, arg) + "Add commas for numeric values" + return f"{value}{arg}" @register.filter def custom_hash(value): "This creates a custom akid generation" - return '{}.{}'.format(value, 'fakehash') + return "{}.{}".format(value, "fakehash") @register.filter def is_defined(value): @@ -348,15 +342,14 @@ def is_defined(value): @register.filter def is_nonblank(value): - """ - The filter is_nonblank returns True if the string does not appear blank + """The filter is_nonblank returns True if the string does not appear blank when rendered - that is, it consists of more than just whitespace and invisible HTML. For example the strings with spaces and \t , and   , and

 
would all return False. """ if value: - return bool(re.sub(r'\s', '', strip_tags(value).replace(' ',''))) + return bool(re.sub(r"\s", "", strip_tags(value).replace(" ",""))) return False @register.filter @@ -372,25 +365,23 @@ def columns(value, cols): @register.filter def referring_akid(value, akid): + """example:{% filter referring_akid:akid|tag_links:"source=taf" %}{% include_tmpl page.followup.taf_body escaped %}{% endfilter %} """ - example:{% filter referring_akid:akid|tag_links:"source=taf" %}{% include_tmpl page.followup.taf_body escaped %}{% endfilter %} - """ - return re.sub(r'(https?://[^"\'() ]+)', '\\1%sreferring_akid=%s' % ( - ('&' if '?' in value else '?'), - akid + return re.sub(r'(https?://[^"\'() ]+)', "\\1%sreferring_akid=%s" % ( + ("&" if "?" in value else "?"), + akid, ), value) @register.filter def collapse_spaces(value): - """ - First replace multiple newlines with a single newline, + """First replace multiple newlines with a single newline, then collapse multiple non-newline whitespace characters """ - return re.sub(r'(?![\r\n])\s+', ' ', re.sub(r'[\r\n]+', '\n', value)) + return re.sub(r"(?![\r\n])\s+", " ", re.sub(r"[\r\n]+", "\n", value)) @register.filter def get(value, key): - if hasattr(value, 'get'): + if hasattr(value, "get"): return value.get(key) elif hasattr(value, key): return getattr(value, key) @@ -401,15 +392,15 @@ def matches(value, regex): @register.filter def strip_nondigits(value): - return re.sub(r'\D', '', value) + return re.sub(r"\D", "", value) @register.filter def remove_blank_lines(value): - return re.sub(r'\n\s*\n', '\n', value) + return re.sub(r"\n\s*\n", "\n", value) @register.filter def is_nonblank(value): - return value != '' + return value != "" @register.filter def ak_text(value, arg): diff --git a/dsa_actionkit/templatetags/ak_universal.py b/dsa_actionkit/templatetags/ak_universal.py index 81909ff..76c32d5 100644 --- a/dsa_actionkit/templatetags/ak_universal.py +++ b/dsa_actionkit/templatetags/ak_universal.py @@ -1,22 +1,22 @@ -""" -These tags seem to be available in base-line (i.e. all forms) +"""These tags seem to be available in base-line (i.e. all forms) so we import register from defaulttags """ from django.conf import settings from django.template.defaulttags import register + @register.filter def single_line(value): "issue: this seems to be pre-loaded tag without actionkit_tags -- diff django version?" - return value.replace('\n',' ') + return value.replace("\n"," ") @register.simple_tag def client_name(): - "is this true? that it's universally available?" - return getattr(settings, 'AK_CLIENT_NAME', '--Site_ClientName--') + "Is this true? that it's universally available?" + return getattr(settings, "AK_CLIENT_NAME", "--Site_ClientName--") @register.simple_tag def client_domain(): - return getattr(settings, 'AK_CLIENT_DOMAIN', 'actionkit.example.com') + return getattr(settings, "AK_CLIENT_DOMAIN", "actionkit.example.com") diff --git a/dsa_actionkit/templatetags/humanize.py b/dsa_actionkit/templatetags/humanize.py index e71011e..9bec93d 100644 --- a/dsa_actionkit/templatetags/humanize.py +++ b/dsa_actionkit/templatetags/humanize.py @@ -1,3 +1,3 @@ -from django.template import loader, Library, Node +from django.template import Library register = Library() diff --git a/dsa_actionkit/templatetags/smartif.py b/dsa_actionkit/templatetags/smartif.py index e71011e..9bec93d 100644 --- a/dsa_actionkit/templatetags/smartif.py +++ b/dsa_actionkit/templatetags/smartif.py @@ -1,3 +1,3 @@ -from django.template import loader, Library, Node +from django.template import Library register = Library() diff --git a/dsa_actionkit/templatetags/switchcase.py b/dsa_actionkit/templatetags/switchcase.py index 7e4a692..116dfe4 100644 --- a/dsa_actionkit/templatetags/switchcase.py +++ b/dsa_actionkit/templatetags/switchcase.py @@ -1,4 +1,4 @@ -from django.template import loader, Library, Node, TemplateSyntaxError +from django.template import Library, Node, TemplateSyntaxError from django.template.base import VariableDoesNotExist register = Library() @@ -8,8 +8,7 @@ @register.tag(name="switch") def do_switch(parser, token): - """ - The ``{% switch %}`` tag compares a variable against one or more values in + """The ``{% switch %}`` tag compares a variable against one or more values in ``{% case %}`` tags, and outputs the contents of the matching block. An optional ``{% else %}`` tag sets off the default output if no matches could be found:: @@ -39,7 +38,7 @@ def do_switch(parser, token): raise TemplateSyntaxError("'%s' tag requires one argument" % tag_name) variable = parser.compile_filter(bits[1]) - class BlockTagList(object): + class BlockTagList: # This is a bit of a hack, as it embeds knowledge of the behaviour # of Parser.parse() relating to the "parse_until" argument. def __init__(self, *names): @@ -49,14 +48,14 @@ def __contains__(self, token_contents): return name in self.names # Skip over everything before the first {% case %} tag - parser.parse(BlockTagList('case', 'endswitch')) + parser.parse(BlockTagList("case", "endswitch")) cases = [] token = parser.next_token() got_case = False got_else = False - while token.contents != 'endswitch': - nodelist = parser.parse(BlockTagList('case', 'else', 'endswitch')) + while token.contents != "endswitch": + nodelist = parser.parse(BlockTagList("case", "else", "endswitch")) if got_else: raise TemplateSyntaxError("'else' must be last tag in '%s'." % tag_name) @@ -64,7 +63,7 @@ def __contains__(self, token_contents): contents = token.contents.split() token_name, token_args = contents[0], contents[1:] - if token_name == 'case': + if token_name == "case": tests = list(map(parser.compile_filter, token_args)) case = (tests, nodelist) got_case = True diff --git a/dsa_actionkit/test.py b/dsa_actionkit/test.py deleted file mode 100644 index 99b962e..0000000 --- a/dsa_actionkit/test.py +++ /dev/null @@ -1,73 +0,0 @@ -import datetime -import os -import re -from sys import platform -import time -try: - from urlparse import urlparse -except ImportError: - # python3 - from urllib.parse import urlparse - -from pyvirtualdisplay import Display - -from django.test import Client, TestCase, override_settings -from django.test import LiveServerTestCase -from selenium import webdriver -from selenium.webdriver.support.ui import Select - -TESTSETTINGS = { - 'AK_TEST': True, -} - -@override_settings(**TESTSETTINGS) -class TemplateTest(LiveServerTestCase): - - mobile_size = (1024, 1000) # mobile w/ scroll - desktop_size = (1920, 1024) - - @classmethod - def setUpClass(cls): - super(TemplateTest, cls).setUpClass() - if platform.startswith('linux'): - size = cls.mobile_size - if os.environ.get('SCREENSIZE') == 'desktop': - size = cls.desktop_size - cls.display = Display(visible=os.environ.get('VISIBLE',0), - size=size) - cls.display.start() - cls.wd = webdriver.Firefox() - - @classmethod - def tearDownClass(cls): - if platform.startswith('linux'): - cls.display.stop() - super(TemplateTest, cls).tearDownClass() - - def _databases_names(*args, **kwargs): - #make things database-less - return [] - - def open(self, url): - self.wd.get("%s%s" % (self.live_server_url, url)) - - def test_screenshots(self): - if os.environ.get('SCREENSHOTS'): - dirname = 'screenshots_{}'.format(os.environ.get('SCREENSIZE', 'mobile')) - try: - os.mkdir(dirname) - except OSError: - pass # we'll overwrite existing screenshots - self.open('/') - links = has_header = self.wd.find_elements_by_xpath('//div[@role="main"]//a') - hrefs = [urlparse(e.get_attribute('href')).path for e in links] - for href in hrefs: - filename = href.replace('/', '_') - self.open(href) - self.wd.save_screenshot('{}/{}.png'.format(dirname, filename)) - - # def test_donate(self, query=''): - # self.open('/donations/donate.1?amounts=17-39-51-other&' + query) - # # test whether 'donation_type' text is present likely for choosing/setting the donation_type - # self.assertTrue(re.search(r'donation_type', self.wd.page_source)) - diff --git a/dsa_actionkit/urls.py b/dsa_actionkit/urls.py new file mode 100644 index 0000000..133c944 --- /dev/null +++ b/dsa_actionkit/urls.py @@ -0,0 +1,29 @@ +from django.contrib.staticfiles.urls import staticfiles_urlpatterns +from django.urls import re_path + +from dsa_actionkit.settings import STATIC_ROOT +from dsa_actionkit.views import ( + event_api_moveon_fake, + event_search_results, + index, + login_context, + logout, + user_password_forgot, +) + +urlpatterns = [ + re_path(r"^context", login_context), + re_path(r"^progress", login_context, name="progress"), + re_path(r"^logout", logout, name="logout"), + re_path(r"^(?P[-.\w]+)?(/(?P[-.\w]+))?$", index), + re_path(r"^forgot/$", user_password_forgot, name="user_password_forgot"), + re_path( + r"^cms/event/(?P[-.\w]+)/search_results/", + event_search_results, + name="event_search_results", + ), + re_path(r"^fake/api/events", event_api_moveon_fake, name="event_api_moveon_fake"), + re_path(r"^fake/stub/reverse", event_api_moveon_fake, name="reverse_donation"), +] +if STATIC_ROOT: + urlpatterns = staticfiles_urlpatterns() diff --git a/dsa_actionkit/views.py b/dsa_actionkit/views.py new file mode 100644 index 0000000..ce517be --- /dev/null +++ b/dsa_actionkit/views.py @@ -0,0 +1,152 @@ +import json +import os +import time +from pathlib import Path +from urllib import parse + +import requests +from django.conf import settings +from django.http import Http404, HttpResponse +from django.shortcuts import redirect, render +from django.views.static import serve + +from dsa_actionkit.moveon_fakeapi import mo_event_data + + +def _get_context_data(request, name=None, page=None, use_referer=False): + from dsa_actionkit.contexts.page_contexts import contexts + port = "4000" + hostport = request.get_host().split(":") + if len(hostport) > 1: + port = hostport[1] + + if use_referer: + paths = None + if request.META.get("HTTP_REFERER"): + paths = parse(request.META["HTTP_REFERER"]).path.split("/") + elif request.GET.get("path"): + paths = request.GET["path"].split("/") + if paths and len(paths) > 1: + name = paths[1] + if len(paths) > 2: + page = paths[2] + + custom_contexts_file = settings.PROJECT_ROOT_PATH / os.environ.get( + "CUSTOM_CONTEXTS", + "contexts.json", + ) + if Path.exists(custom_contexts_file): + try: + contexts.update({"Custom": json.loads(open(custom_contexts_file).read())}) + except ValueError as e: + msg = ( + "JSON Parsing Error for context file {} {}".format( + custom_contexts_file, e.message) + ) + raise Exception(msg) + #first use ?template= if there, otherwise name's template, otherwise homepage + cxt = { + "devenv": { + "enabled": True, + "port": port, + "STATIC_URL": settings.STATIC_URL, + "STATIC_LOCAL": settings.STATIC_LOCAL, + "MO_EVENTS_API": "/fake/api/events", + }, + } + context_data = contexts.get(name, {}) + if page: + context_data = contexts.get(name, {}).get(page, {}) + cxt.update(context_data) + if not context_data: + sections = [] + for section, pages in sorted(contexts.items()): + sections.append([section, sorted(pages.items())]) + cxt.update({ + "page": {"title":"Homepage"}, + "pagelinks": sections}) + if request.GET.get("user_id"): + #for debugging tests based on user.id % 2, e.g. + context_data.setdefault("user", {}).update({"id": int(request.GET.get("user_id"))}) + args = cxt.get("args", {}).copy() + args.update(request.GET.dict()) + cxt["args"] = args + if "akid" not in cxt: + cxt["akid"] = cxt["args"].get("akid") + cxt["request"] = request + cxt["js_context"] = '""' # FUTURE: what should go in here? + return cxt + + +def index(request, name=None, page=None): + cxt = _get_context_data(request, name, page) + template = request.GET.get("template", + cxt.get("filename", "homepagetest.html")) + + return render(request, template, cxt) + +def login_context(request): + cxt = _get_context_data(request, use_referer=True) + from dsa_actionkit.contexts.event_context_json import event_json + event_json_copy = event_json.copy() + coming_from = request.GET.get("url","") + if "event" in coming_from \ + or "logged_in" in coming_from \ + or "survey_logged_in" in coming_from: + if not request.GET.get("login") and "survey_logged_in" not in coming_from: + del event_json_copy["name"] + return HttpResponse( + "actionkit.forms.onContextLoaded(%s)" % json.dumps(event_json_copy)) + elif cxt.get("context"): + return HttpResponse("actionkit.forms.onContextLoaded(%s)" % json.dumps(cxt["context"])) + else: + return HttpResponse( + #text key has all the generic error messages + 'actionkit.forms.onContextLoaded({"text": %s})' % json.dumps(event_json["text"])) + +def user_password_forgot(request): + return HttpResponse("unimplemented") + +def logout(request): + if request.GET.get("next"): + return redirect(request.GET.get("next")) + return redirect("/logout.html") + +def event_search_results(request, page): + cxt = _get_context_data(request, "events", "WILL_USE_REFERER_HEADER", use_referer=True) + # special query results context: + all = cxt["args"].get("all") == "1" + cxt.update({"all": all}) + if cxt.get("SLOW_SEARCH"): + # This allows us to test for race conditions + time.sleep(2) + search_results = render(request, "event_search_results.html", cxt) + return HttpResponse("actionkit.forms.onEventSearchResults({})" + .format(json.dumps(search_results))) + +def event_api_moveon_fake(request): + """Fake representation of MoveOn events api""" + cxt = _get_context_data(request, "events", "WILL_USE_REFERER_HEADER", use_referer=True) + events = cxt.get("events", []) + if cxt.get("SLOW_API"): + # This allows us to test for race conditions + time.sleep(2) + if cxt.get("500_API"): + raise Exception("Cause failure to allow graceful degradation") + search_results = [mo_event_data(evt) for evt in events] + return HttpResponse(json.dumps({"events": search_results}), content_type="application/json") + +def proxy_serve(request, path, document_root=None, show_indexes=False): + + try: + return serve(request, path, document_root, show_indexes) + except Http404: + prefix = request.path.split("/")[1] + content = requests.get( + f"https://roboticdogs.actionkit.com/{prefix}/{path}", + verify=False, + timeout=10, + ) + if content.status_code == 200: + return HttpResponse(content.content, content_type=content.headers["Content-Type"]) + raise Http404 diff --git a/pyproject.toml b/pyproject.toml index 551a22f..806736b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -13,8 +13,10 @@ description = "actionkit-templates allows you to view your ActionKit templates l dependencies = [ "django==3.2.6", "requests>=2.22.0", + "pytest-django", "django_extensions", "werkzeug", + "ruff" ] keywords = ["actionkit"] classifiers = [ @@ -39,3 +41,18 @@ test = ["selenium>=3.8.0", "pyvirtualdisplay"] [tool.setuptools.packages] find = { namespaces = false } + +[tool.ruff] +fix = true +select = ["ALL"] +per-file-ignores = { "tests/**/*.py" = [ + "S101", + "D100", + "D103", + "ANN201", + "ANN001", + "INP001", +] } + +[tool.ruff.pydocstyle] +convention = "google" \ No newline at end of file diff --git a/tests/test_user_landing_page.py b/tests/test_user_landing_page.py new file mode 100644 index 0000000..1b9b436 --- /dev/null +++ b/tests/test_user_landing_page.py @@ -0,0 +1,12 @@ +import pytest +from django.urls import reverse + + +@pytest.mark.parametrize("dues_amount", [(3, 100)]) +def test_dues_amount_correct_after_logging_in(django_user_model, client, dues_amount): + member = django_user_model.object.create(status="M", dues_amount=dues_amount) + client.force_login(member) + + response = client.get(reverse("dues_landing_page")) + + assert dues_amount in response.content.decode() diff --git a/tests/tests.py b/tests/tests.py deleted file mode 100644 index d46f552..0000000 --- a/tests/tests.py +++ /dev/null @@ -1,8 +0,0 @@ -import re - - -class TemplateTest: - def test_donate(self): - self.open("/donations/donate.1?amounts=17-39-51-other") - # test whether 'donation_type' text is present likely for choosing/setting the donation_type - self.assertTrue(re.search(r"donation_type", self.wd.page_source))