From a9987efbe264941af009ad3b927e99c3a16d81ef Mon Sep 17 00:00:00 2001 From: Ross Karchner Date: Mon, 7 Nov 2011 23:59:52 -0500 Subject: [PATCH] ported links functionality to Django, prep'ed app for new billing rules and python2.7 --- account/forms.py | 1 - account/views.py | 1 - app.yaml | 19 ++-- appengine_config.py | 5 +- events/models.py | 1 - eventsite/__init__.py | 2 +- eventsite/admin/forms.py | 10 +- eventsite/admin/views.py | 10 +- eventsite/models.py | 1 - eventsite/views.py | 1 - links/forms.py | 39 +------ links/urls.py | 2 +- links/views.py | 29 +++++- main.py | 11 +- readme.md | 4 +- settings.py | 2 +- sources/forms.py | 1 + sources/models.py | 49 +++++---- sources/tasks.py | 148 ++++++++------------------- sources/urls.py | 4 +- sources/views.py | 2 +- templates/account/profile-setup.html | 1 + templates/base.html | 1 - templates/eventsite/front-page.html | 2 +- templates/eventsite/newsletter.html | 1 - templates/eventsite/sidebar.html | 18 +--- templates/eventsite/tagpage.html | 1 - templates/eventsite/week.html | 1 - templates/eventsite/week.xml | 1 - templates/links/add.html | 40 ++++++++ templates/links/review.html | 50 +++++++++ 31 files changed, 221 insertions(+), 237 deletions(-) create mode 100644 templates/links/add.html create mode 100644 templates/links/review.html diff --git a/account/forms.py b/account/forms.py index 0fdd568..d5796bc 100755 --- a/account/forms.py +++ b/account/forms.py @@ -15,7 +15,6 @@ class ProfileForm(forms.Form): nickname = forms.CharField(max_length=255, help_text="What you want to be known as on the site") email=forms.EmailField(required=True, help_text="Where should we send email?", widget=EmailInput) - subscribe = forms.BooleanField(required=False, help_text="Do you want to get the weekly events email?") link=forms.URLField(required=False, help_text="This can be the URL of your blog, twitter page, LinkedIn profile, homepage, or anything else.", widget=TextInput(attrs={'placeholder':'http://whatever'})) diff --git a/account/views.py b/account/views.py index 2946a28..870e0ef 100755 --- a/account/views.py +++ b/account/views.py @@ -50,7 +50,6 @@ def save_profile(profile, form): profile.slug=unicode(slugify(nickname)) profile.confirmed_at=datetime.now() profile.link=form.cleaned_data['link'] or None - profile.subscribes=form.cleaned_data['subscribe'] profile.put() if profile.subscribes: site=get_site() diff --git a/app.yaml b/app.yaml index 6c86c0b..5d4b497 100755 --- a/app.yaml +++ b/app.yaml @@ -1,22 +1,29 @@ -application: techevents -version: cleanup -runtime: python +application: eventgrinder2 +version: cleanup2 +runtime: python27 api_version: 1 +threadsafe: true + +libraries: +- name: PIL + version: "1.1.7" +- name: django + version: "1.2" -handlers: +handlers: - url: /static/([^/]*)/(.*) static_files: static/\2 upload: static/(.*) expiration: "24d" - url: /tasks.* - script: main.py + script: main.application login: admin - url: .* - script: main.py + script: main.application builtins: - datastore_admin: on \ No newline at end of file diff --git a/appengine_config.py b/appengine_config.py index b737722..25d832b 100755 --- a/appengine_config.py +++ b/appengine_config.py @@ -2,11 +2,8 @@ import os -os.environ['DJANGO_SETTINGS_MODULE'] = 'settings' -from google.appengine.dist import use_library -use_library('django', '1.2') - +sys.path= [os.path.join(os.path.dirname(__file__), 'shared'), os.path.join(os.path.dirname(__file__), '.')]+sys.path diff --git a/events/models.py b/events/models.py index c8cf434..f28c426 100755 --- a/events/models.py +++ b/events/models.py @@ -1,7 +1,6 @@ import datetime from google.appengine.ext import db from google.appengine.api import users -from sources.models import ICalendarSource from eventsite.models import Eventsite from account.models import Profile from utility import slugify diff --git a/eventsite/__init__.py b/eventsite/__init__.py index da5fe67..5deb128 100755 --- a/eventsite/__init__.py +++ b/eventsite/__init__.py @@ -23,7 +23,7 @@ def get_site(key_name=None): def site_required(func): def no_site(request, *args, **kwargs): if not request.site: - return HttpResponse("No calendar with that name exists (yet!)") + return HttpResponseRedirect("/admin/create/") else: return HttpResponse("%s will return soon!" % request.site.name) diff --git a/eventsite/admin/forms.py b/eventsite/admin/forms.py index 59a85de..5f7e286 100755 --- a/eventsite/admin/forms.py +++ b/eventsite/admin/forms.py @@ -11,19 +11,15 @@ class SiteCreateForm(forms.Form): name = forms.CharField(max_length=255, required=True) timezone=forms.ChoiceField(choices=timezones) - slug=forms.CharField(max_length=255, required=True) - audience=forms.CharField(max_length=255, required=True) + + class SiteDetailsForm(forms.Form): name = forms.CharField(max_length=255, required=True) timezone=forms.ChoiceField(choices=timezones) - audience=forms.CharField(max_length=255, required=True) - google_analytics_code=forms.CharField(max_length=255, required=False) - google_site_verification=forms.CharField(max_length=255, required=False) twitter=forms.CharField(max_length=255, required=False) - bsa_code=forms.CharField(max_length=255, required=False, widget=forms.Textarea) offline=forms.BooleanField(required=False) - hostnames=forms.CharField(max_length=255, required=False) + def clean_hostnames(self): diff --git a/eventsite/admin/views.py b/eventsite/admin/views.py index e2c0373..a449d82 100755 --- a/eventsite/admin/views.py +++ b/eventsite/admin/views.py @@ -37,10 +37,9 @@ def create_site(request): if form.is_valid(): new_site=models.Eventsite(name=form.cleaned_data['name'].strip(), timezone= form.cleaned_data['timezone'].strip(), - audience=form.cleaned_data['audience'].strip(), hostnames=[hostname,], key_name=hostname, - slug=form.cleaned_data['slug']) + slug=str(slugify(hostname))) new_site.put() return HttpResponseRedirect(reverse('admin-home')) return render_to_response('eventsite/admin.html', locals(), context_instance=RequestContext(request)) @@ -66,12 +65,7 @@ def edit_site(request): if form.is_valid(): # All validation rules pass site.name=form.cleaned_data['name'].strip() site.timezone= form.cleaned_data['timezone'].strip() - site.audience=form.cleaned_data['audience'].strip() - site.hostnames=form.cleaned_data['hostnames'] - site.google_site_verification=form.cleaned_data['google_site_verification'].strip() - site.google_analytics_code=form.cleaned_data['google_analytics_code'].strip() site.twitter=form.cleaned_data['twitter'] or None - site.bsa_code=form.cleaned_data['bsa_code'] or None site.offline=form.cleaned_data['offline'] or None site.put() site.expire_assets() @@ -81,7 +75,7 @@ def edit_site(request): site=get_site() if site: site_details={'name':site.name, 'timezone':site.timezone, 'slug':site.slug, - 'audience': site.audience, 'hostnames':",".join(site.hostnames), + 'hostnames':",".join(site.hostnames), 'google_analytics_code':site.google_analytics_code, 'google_site_verification':site.google_site_verification, 'twitter':site.twitter, diff --git a/eventsite/models.py b/eventsite/models.py index a972d9e..2c34497 100755 --- a/eventsite/models.py +++ b/eventsite/models.py @@ -30,7 +30,6 @@ class Eventsite(db.Model): original_logo_version=db.IntegerProperty() logo=db.BlobProperty() logo_asset_href=db.StringProperty() - audience=db.TextProperty(required=False) google_analytics_code=db.TextProperty(required=False) google_site_verification=db.TextProperty(required=False) disqus_shortname=db.TextProperty(required=False) diff --git a/eventsite/views.py b/eventsite/views.py index 5dd32d1..d62b540 100755 --- a/eventsite/views.py +++ b/eventsite/views.py @@ -148,7 +148,6 @@ def this_week_rss(request): -@cache_page(60 * 10) @site_required def front_page(request, tag=None): start=request.site.today diff --git a/links/forms.py b/links/forms.py index 92c1743..c10b2a1 100755 --- a/links/forms.py +++ b/links/forms.py @@ -1,42 +1,13 @@ -from datetime import date -import logging - -from tipfy import RequestHandler, Response, redirect, cached_property -from tipfy.ext.jinja2 import Jinja2Mixin -from tipfy.ext.wtforms import Form, fields, validators, widgets -from tipfy.ext.wtforms.validators import ValidationError - -from tipfy.ext.db import populate_entity - -from wtforms.ext.dateutil.fields import DateField - - -from pytz.gae import pytz - - -# a set of HTML5 widgets for wtforms - -from wtforms.widgets import Input - -REQUIRED = validators.required() +from django import forms from models import Link - -class LinkWidget(Input): - def __init__(self, input_type='url'): - if input_type is not None: - self.input_type = input_type - - - - -class AddLinkForm(Form): - name = fields.TextField('Site Name', validators=[REQUIRED]) - href=fields.TextField('URL', validators=[validators.URL(), REQUIRED], widget=LinkWidget()) +class AddLinkForm(forms.Form): + name = forms.CharField(max_length=500) + href=forms.URLField() def save(self): - new_link=Link(**self.data) + new_link=Link(**self.cleaned_data) new_link.status='submitted' new_link.put() diff --git a/links/urls.py b/links/urls.py index 2bbb0fe..7835284 100755 --- a/links/urls.py +++ b/links/urls.py @@ -3,7 +3,7 @@ urlpatterns = patterns('links.views', url(r'^add/$','add', name="add_link"), - # url(r'^review/$','review', name="review_links"), + url(r'^review/$','review', name="review_links"), # url(r'^change/$','add', name="change_link"), diff --git a/links/views.py b/links/views.py index 1ce32f7..93a0b5e 100644 --- a/links/views.py +++ b/links/views.py @@ -3,11 +3,34 @@ from django.template import RequestContext from django.contrib import messages -from account.utility import get_current_user, profile_required, get_current_profile +from account.utility import get_current_user, profile_required, get_current_profile, admin_required from eventsite import site_required - +from forms import AddLinkForm +from models import Link @site_required def add(request): - return(render_to_response('links/add.html', locals(), context_instance=RequestContext(request))) \ No newline at end of file + if request.method == 'POST': + form=AddLinkForm(request.POST) + if form.is_valid(): + form.save() + messages.add_message(request, messages.INFO, "Thank you for submitting a link!") + return redirect('/') + + + else: + form=AddLinkForm() + return(render_to_response('links/add.html', locals(), context_instance=RequestContext(request))) + + +@admin_required +def review(request): + if request.method=='POST': + link=Link.get_by_id(int(request.POST['id'])) + link.status=request.POST['action'] + link.put() + + approved_links=Link.all().filter('status =', 'approved') + submitted_links=Link.all().filter('status =', 'submitted') + return(render_to_response('links/review.html', locals(), context_instance=RequestContext(request))) \ No newline at end of file diff --git a/main.py b/main.py index e447d9c..673245c 100755 --- a/main.py +++ b/main.py @@ -8,9 +8,6 @@ # Django imports and other code go here... import os os.environ['DJANGO_SETTINGS_MODULE'] = 'settings' -from google.appengine.dist import use_library -use_library('django', '1.2') - import django.core.handlers, django.core.handlers.wsgi @@ -20,10 +17,4 @@ -def main(): - sys.path= [os.path.join(os.path.dirname(__file__), 'shared'), os.path.join(os.path.dirname(__file__), '.')]+sys.path - application = django.core.handlers.wsgi.WSGIHandler() - util.run_wsgi_app(application) - -if __name__ == '__main__': - main() \ No newline at end of file +application = django.core.handlers.wsgi.WSGIHandler() diff --git a/readme.md b/readme.md index a408998..14254ee 100644 --- a/readme.md +++ b/readme.md @@ -1,6 +1,6 @@ #What is this crazy thing? -This is the current, production version of "Eventgrinder"-- which runs some calendar aggregator sites, like dctechevents.com +This is a "cleanup" branch of "Eventgrinder"-- which runs some calendar aggregator sites, like dctechevents.com #Whatgrinder? @@ -13,8 +13,6 @@ Lot's of reasons! Here's a few: * I didn't concieve of it as open source, and it never occured to me that someone else might see the code. * Testing? LOL * There are a lot of half-implemented ideas in the code. -* It only runs on AppEngine -* It's written in at least two frameworks (Django and Tipfy), with a little bit of hacky WSGI middleware thrown in for reasons I forget. # What is most broken? diff --git a/settings.py b/settings.py index 92fc76b..14acd40 100755 --- a/settings.py +++ b/settings.py @@ -97,7 +97,7 @@ #'messaging.messaging_context' ) -ROOT_URLCONF = 'django_urls' +ROOT_URLCONF = 'urls' ROOT_PATH = os.path.dirname(__file__) diff --git a/sources/forms.py b/sources/forms.py index efdf195..265eb42 100755 --- a/sources/forms.py +++ b/sources/forms.py @@ -21,6 +21,7 @@ class ICalendarEditForm(forms.Form): source_key=forms.CharField(required=False) def save(self): + from models import ICalendarSource cleaned_data=self.cleaned_data profile=get_current_profile() from models import ICalendarSource diff --git a/sources/models.py b/sources/models.py index 98524c5..f3f0473 100755 --- a/sources/models.py +++ b/sources/models.py @@ -14,6 +14,8 @@ from google.appengine.api.labs import taskqueue from google.appengine.api import memcache +from sources.tasks import process_ical, process_gdata + from urllib import unquote import gdata.calendar.service @@ -49,7 +51,9 @@ def fetch(self,started=None, timestamp=None): format_start="%Y%m%d%H%M" if not started: started=str(datetime.now()) if not timestamp:timestamp= datetime.now().strftime("%Y%m%d%H%M") - if self.ical_href.startswith('http://www.google.com/calendar/ical/'): + + if self.ical_href.startswith('http://www.google.com/calendar/ical/') or self.ical_href.startswith('https://www.google.com/calendar/ical/'): + gcal_id=unquote(self.ical_href[36:].split('/')[0]) query = gdata.calendar.service.CalendarEventQuery(gcal_id, 'public', 'full-noattendees') query.start_min= self.site.today.strftime("%Y-%m-%d") @@ -57,33 +61,38 @@ def fetch(self,started=None, timestamp=None): query.start_max=(date.today()+relativedelta(months=3)).strftime("%Y-%m-%d") query.singleevents='true' result=urlfetch.fetch(query.ToUri(), allow_truncated=False, deadline=10) + logging.warning("fetching %s" % result.content) if result.status_code == 200: detection=chardet.detect(result.content) self.last_fetch=datetime.now() + self.content=result.content.decode(detection['encoding']) self.put() - cache_key="%s-%s-%s" %(self.site.slug, self.slug,timestamp) - memcache.add(cache_key, result.content.decode(detection['encoding']),600) - logging.warning("cached gdata with key %s"% cache_key) - taskqueue.add(url='/sources/split_gdata/', params={'ical_key': self.key(), - 'cache_key':cache_key, - 'timestamp':timestamp}, - name=cache_key - ) - logging.warning("enqueued splitting of %s" % self.ical_href) + process_gdata(self) + #cache_key="%s-%s-%s" %(self.site.slug, self.slug,timestamp) + #memcache.add(cache_key, ,600) + #logging.warning("cached gdata with key %s"% cache_key) + #taskqueue.add(url='/sources/split_gdata/', params={'ical_key': self.key(), + # 'cache_key':cache_key, + # 'timestamp':timestamp}, + # name=cache_key + # ) + #logging.warning("enqueued splitting of %s" % self.ical_href) return - result=urlfetch.fetch(self.ical_href, allow_truncated=True, deadline=5) + result=urlfetch.fetch(self.ical_href, allow_truncated=False, deadline=5) if result.status_code == 200: detection=chardet.detect(result.content) self.last_fetch=datetime.now() + self.content=result.content.decode(detection['encoding']) self.put() - cache_key="%s-%s-%s" %(self.site.slug, self.slug,timestamp) - memcache.add(cache_key, result.content.decode(detection['encoding']),600) - logging.warning("cached ical with key %s"% cache_key) - taskqueue.add(url='/sources/split_ical/', params={'ical_key': self.key(), - 'cache_key':cache_key, - 'timestamp':timestamp}, - name=cache_key - ) - logging.warning("enqueued splitting of %s" % self.ical_href) + process_ical(self) + #cache_key="%s-%s-%s" %(self.site.slug, self.slug,timestamp) + #memcache.add(cache_key, result.content.decode(detection['encoding']),600) + #logging.warning("cached ical with key %s"% cache_key) + #taskqueue.add(url='/sources/split_ical/', params={'ical_key': self.key(), + # 'cache_key':cache_key, + # 'timestamp':timestamp}, + # name=cache_key + # ) + #logging.warning("enqueued splitting of %s" % self.ical_href) diff --git a/sources/tasks.py b/sources/tasks.py index a3cdabf..2e7c06d 100755 --- a/sources/tasks.py +++ b/sources/tasks.py @@ -1,4 +1,3 @@ -from models import ICalendarSource from django.http import HttpResponse from dateutil.parser import parse from google.appengine.api.labs import taskqueue @@ -11,6 +10,7 @@ from google.appengine.api import memcache from google.appengine.api import urlfetch + import gdata.calendar from vobject.icalendar import stringToDate, stringToDateTime @@ -28,35 +28,22 @@ -def split_gdata(request): - try: - if request.method == 'POST': - key=db.Key(request.POST.get('ical_key')) - source=ICalendarSource.get(key) - gdata_source=memcache.get(request.POST.get('cache_key')) - memcache.delete(request.POST.get('cache_key')) - feed=gdata.calendar.CalendarEventFeedFromString(gdata_source) - cal_count=0 - for gevent in feed.entry: - cal_count=cal_count +1 - source_cache_key=request.POST.get('cache_key') - cache_key=source_cache_key +"-"+ str(cal_count) - memcache.set(cache_key, gevent.ToString(),1200) - - params=params={'cache_key': cache_key, - 'ical_key': request.POST['ical_key']} - taskqueue.add(url='/events/parse_one_gdata/', - params=params, - name=cache_key,countdown=30) +def process_gdata(source): + from events.models import Event + try: + gdata_source=source.content + feed=gdata.calendar.CalendarEventFeedFromString(gdata_source) + cal_count=0 + for gevent in feed.entry: + Event.from_gdata(gevent, source) - except urlfetch.DownloadError: - raise + except urlfetch.DownloadError: + raise - except Exception,e: - logging.error("%s in \n%s"% (traceback.format_exc(),str(request.POST))) + except Exception,e: + logging.error(traceback.format_exc()) - return HttpResponse("OK") @@ -69,7 +56,7 @@ def fetch_icals(request): q=ICalendarSource.all().filter('status = ', 'approved').filter('last_fetch < ', parsed_started- relativedelta(hours=+3)) if cursor: q=q.with_cursor(cursor) - cals= q.fetch(1) + cals= q.fetch(100) if cals: params={'cursor': q.cursor(), 'started': started} @@ -86,84 +73,31 @@ def fetch_icals(request): return HttpResponse("OK") -def split_ical(request): - - - - def is_future(ical): - return True - v_start=ical.find("BEGIN:VEVENT") - start_line=ical.find('DTSTART:',v_start) - end_line=ical.find("\n", start_line) - logging.warning("startline: \n %s"% ical[start_line:end_line]) - if end_line < 0: - end_line=ical.find("\r\n") - try: - dateobject= parse(ical[start_line+8:end_line]) - except ValueError: - try: - dateobject= stringToDateTime(ical[start_line+8:end_line]) - except: - logging.warning("Could not parse DTSTART %s" % ical[start_line+8:end_line]) - return True - if hasattr(dateobject, 'tzinfo') and dateobject.tzinfo: - - diff= utc.localize(datetime.utcnow()) - dateobject - else: - diff= datetime.now() - dateobject - - return diff < timedelta(1) - - - - if request.method == 'POST': - key=db.Key(request.POST.get('ical_key')) - source=ICalendarSource.get(key) - - def split_ical_file(ical): - first_vevent_start=ical.find('BEGIN:VEVENT') - cal_meta=ical[0:first_vevent_start] - #print cal_meta - - def next_vevent(start): - end=ical.find('END:VEVENT',start) - if end > -1: - end=end+10 - cal=cal_meta+ical[start:end]+"\nEND:VCALENDAR" - return (cal, end) - else: - return(None, None) - vevent, index=next_vevent(first_vevent_start) - while vevent: - yield vevent - vevent, index=next_vevent(index) - try: - ical_source=memcache.get(request.POST.get('cache_key')) - memcache.delete(request.POST.get('cache_key')) - - if not ical_source: - logging.error("nothing in cache") - return HttpResponse("nothing in cache") - if ical_source: - cal_count=0 - for event_ical in split_ical_file(ical_source): - cal_count=cal_count +1 - if is_future(event_ical): - source_cache_key=request.POST.get('cache_key') - cache_key=source_cache_key +"-"+ str(cal_count) - memcache.set(cache_key, event_ical,1200) - - params=params={'cache_key': cache_key, - 'ical_key': request.POST['ical_key']} - logging.warning(params) - taskqueue.add(url='/events/parse_one_event/', - params=params, - name=cache_key,countdown=30) - - - except DeadlineExceededError: - return HttpResponse("Deadline Exceeded!") - except Exception,e: - logging.error("%s in \n%s"% (traceback.format_exc(),str(request.POST))) - return HttpResponse("OK") \ No newline at end of file +def process_ical(source): + from events.models import Event + try: + ical=source.content + first_vevent_start=ical.find('BEGIN:VEVENT') + cal_meta=ical[0:first_vevent_start] + + def next_vevent(start): + end=ical.find('END:VEVENT',start) + if end > -1: + end=end+10 + cal=cal_meta+ical[start:end]+"\nEND:VCALENDAR" + return (cal, end) + else: + return(None, None) + vevent, index=next_vevent(first_vevent_start) + while vevent: + event=Event.from_vcal(vevent, source) + vevent, index=next_vevent(index) + + + + except DeadlineExceededError: + return HttpResponse("Deadline Exceeded!") + except Exception,e: + logging.error(traceback.format_exc()) + return HttpResponse("OK") \ No newline at end of file diff --git a/sources/urls.py b/sources/urls.py index 9988229..c850e87 100755 --- a/sources/urls.py +++ b/sources/urls.py @@ -1,6 +1,6 @@ from django.conf.urls.defaults import * from views import add_source, sources, manage_sources, save_ical, start_fetch_icals, opml, json -from tasks import fetch_icals, split_ical, split_gdata +from tasks import fetch_icals urlpatterns = patterns('events', @@ -11,8 +11,6 @@ url(r'^add/$', add_source, name="add-source"), url(r'^save/$', save_ical, name="save-ical"), url(r'^fetch/$', fetch_icals, name="fetch-icals-task"), - url(r'^split_gdata/$', split_gdata ), - url(r'^split_ical/$', split_ical, name="split_ical"), url(r'^start_fetch_icals/$',start_fetch_icals ) ) diff --git a/sources/views.py b/sources/views.py index 8b239ec..7c77075 100755 --- a/sources/views.py +++ b/sources/views.py @@ -2,7 +2,7 @@ from django.http import HttpResponse, HttpResponseRedirect from django.template import RequestContext from django.contrib import messages - +from models import ICalendarSource from forms import ICalendarEditForm, ICalApprovalForm from account.utility import profile_required, userlevel_required from eventsite import site_required diff --git a/templates/account/profile-setup.html b/templates/account/profile-setup.html index a6f2c5f..3531402 100755 --- a/templates/account/profile-setup.html +++ b/templates/account/profile-setup.html @@ -6,6 +6,7 @@
+

Set up your profile

{% include "account/edit_profile_form.html" %}
diff --git a/templates/base.html b/templates/base.html index f1e3544..7f9d00d 100755 --- a/templates/base.html +++ b/templates/base.html @@ -8,7 +8,6 @@ {% block opengraph %} - {% endblock %} diff --git a/templates/eventsite/front-page.html b/templates/eventsite/front-page.html index 2bdd580..4f98ea0 100755 --- a/templates/eventsite/front-page.html +++ b/templates/eventsite/front-page.html @@ -1,4 +1,4 @@ -{% extends "base-cacheable.html" %} +{% extends "base.html" %} {% load cdn_helper %} {% load event_tags %} {% load utility %} diff --git a/templates/eventsite/newsletter.html b/templates/eventsite/newsletter.html index 7e6a982..8a260b4 100755 --- a/templates/eventsite/newsletter.html +++ b/templates/eventsite/newsletter.html @@ -41,7 +41,6 @@

{{ site.name }} for the week of {{ start|date:"F j, Y"}}

-
{{site.name}} is a calendar for {{site.audience}}
Please consider forwarding this along to your friends and colleagues in the community. If you find it useful, they might too.
diff --git a/templates/eventsite/sidebar.html b/templates/eventsite/sidebar.html index 08b64b8..d981f4b 100755 --- a/templates/eventsite/sidebar.html +++ b/templates/eventsite/sidebar.html @@ -1,22 +1,6 @@
-{% if site.bsa_code %} - -{{ site.bsa_code|safe }} - -{% else %} - - -{% endif %} +
diff --git a/templates/eventsite/tagpage.html b/templates/eventsite/tagpage.html index 73015ea..e1a0e96 100755 --- a/templates/eventsite/tagpage.html +++ b/templates/eventsite/tagpage.html @@ -11,7 +11,6 @@ {% block opengraph %} - {% endblock opengraph %} diff --git a/templates/eventsite/week.html b/templates/eventsite/week.html index e5bfd3d..1bcc2d5 100755 --- a/templates/eventsite/week.html +++ b/templates/eventsite/week.html @@ -13,7 +13,6 @@ {% block opengraph %} - {% endblock opengraph %} diff --git a/templates/eventsite/week.xml b/templates/eventsite/week.xml index c89d012..7477766 100644 --- a/templates/eventsite/week.xml +++ b/templates/eventsite/week.xml @@ -6,7 +6,6 @@ en-us rosskarchner@gmail.com (Ross Karchner) - a calendar for {{site.audience}} This Week on {{ site.name }} http://{{site.host}}/week-of/{{start|date:"c"}} diff --git a/templates/links/add.html b/templates/links/add.html new file mode 100644 index 0000000..fe6132a --- /dev/null +++ b/templates/links/add.html @@ -0,0 +1,40 @@ +{% extends "base.html" %} +{% load cdn_helper %} + + +{% block content %} +
+
+

submit a community link

+ + +
+
+ + + +
+
+
+
{{form.name.label_tag}} + {{form.name}} {{form.name.help_text}} + {{form.name.errors}} +
+
{{form.href.label_tag}} + {{form.href}} {{form.href.help_text}} + {{form.href.errors}} +
+ + +
+
+ +
+
+ +
+ +
+ + +{% endblock %} \ No newline at end of file diff --git a/templates/links/review.html b/templates/links/review.html new file mode 100644 index 0000000..58dada8 --- /dev/null +++ b/templates/links/review.html @@ -0,0 +1,50 @@ +{% extends "base.html" %} +{% load cdn_helper %} + + +{% block content %} +
+
+

Review community links

+ + +
+
+ + + +
+
+

Submitted Links

+ {% for link in submitted_links %} + {{link.name}}
+ {{ link.href }} + + + set to: +
+ {% empty %} + no submitted links + {% endfor %} +

Approved links

+ {% for link in approved_links %} + {{link.name}}
+ {{ link.href }} +
+ + set to: +

+ {% empty %} + No approved links + + {% endfor %} + +
+
+ +
+ +
+ + +{% endblock %} \ No newline at end of file