Skip to content
This repository has been archived by the owner on Feb 27, 2024. It is now read-only.

Commit

Permalink
Add Google Calendar integration. Update jquery, fullcalendar.
Browse files Browse the repository at this point in the history
  • Loading branch information
inducer committed Mar 12, 2013
1 parent 26f13a6 commit 41d7d43
Show file tree
Hide file tree
Showing 11 changed files with 10,672 additions and 8,885 deletions.
126 changes: 97 additions & 29 deletions synoptic/__init__.py
Expand Up @@ -40,6 +40,8 @@ def get_static_file(filename):



# {{{ import backup/initial content

def import_file(dbsession, text):
lines = text.split("\n")

Expand Down Expand Up @@ -68,6 +70,8 @@ def import_file(dbsession, text):

dbsession.commit()

# }}}




Expand All @@ -79,6 +83,16 @@ def kill_hms_in_time_struct(t_struct):



def get_google_calendar_tag(entry_dict):
from hashlib import md5
md5_obj = md5()
md5_obj.update(str(entry_dict.get("url")))
return "gcal-"+md5_obj.hexdigest()[:10]




# {{{ HTTP middleware

class DBSessionInjector(object):
def __init__(self, sub_app, dburl, exists, echo=False):
Expand Down Expand Up @@ -199,9 +213,9 @@ def respond(self, *args, **kwargs):
resp = Response(self.environ, self.start_response, *args, **kwargs)
return resp()

# }}}



# {{{ URL dispatch

class ApplicationBase(object):
def __init__(self, table, allowed_networks=[]):
Expand Down Expand Up @@ -247,6 +261,8 @@ def __call__(self, environ, start_response):
from paste.httpexceptions import HTTPNotFound
raise HTTPNotFound()

# }}}




Expand Down Expand Up @@ -275,6 +291,7 @@ def __init__(self, urlprefix="/", allowed_networks=[]):
(r'tags/rename$', self.http_rename_tag),
(r'calendar$', self.http_calendar),
(r'mobile-calendar$', self.http_mobile_calendar),
(r'calendar/event_sources$', self.http_calendar_event_sources),
(r'calendar/data$', self.http_calendar_data),
(r'app/get_all_js$', self.http_get_all_js),
(r'tag-color-css$', self.http_get_tag_color_css),
Expand All @@ -289,7 +306,8 @@ def __init__(self, urlprefix="/", allowed_networks=[]):
def set_quit_func(self, quit_func):
self.quit_func = quit_func

# tools -------------------------------------------------------------------
# {{{ tools

def item_to_json(self, item):
result = item.as_json()
result['contents_html'] = item.contents_html()
Expand Down Expand Up @@ -354,7 +372,41 @@ def get_json_items(self, session, model, parsed_query, max_timestamp):

return result

# page handlers -----------------------------------------------------------
def get_config_info_by_tag(self, datamodel, dbsession, tag):
"""Return a list of dictionaries containing configuration information
from notes with *tag* which are formatted like this::
* url: https://bladiblah
* color: #4433cc
"""

tags = dbsession.query(Tag).filter_by(name=tag)

entries = []

if tags.count():
google_calendar_tag = tags.one()

from sqlalchemy.sql import select
qry = select([datamodel.itemversions],
from_obj=get_current_itemversions_join(datamodel)) \
.where(ItemVersion.tags.any(id=google_calendar_tag.id))

import re
config_entry_re = re.compile(r"^\s*(?:\*\s+)?([a-zA-Z0-9]+)\s*:\s*(.*)\s*$",
re.MULTILINE)
for item_ver in dbsession.query(ItemVersion).from_statement(qry):
entry = {}
entries.append(entry)
for match in config_entry_re.finditer(item_ver.contents):
entry[match.group(1)] = match.group(2)

return entries

# }}}

# {{{ page handlers

def http_index(self, request):
from synoptic.html import main_page, Context
ctx = Context()
Expand Down Expand Up @@ -862,6 +914,23 @@ def http_mobile_calendar(self, request):
from html import mobile_calendar_page
return request.respond(mobile_calendar_page({}))

def http_calendar_event_sources(self, request):
event_sources = ["/calendar/data"]

for entry_dict in self.get_config_info_by_tag(
request.datamodel, request.dbsession, u"googlecalendar"):
if "url" not in entry_dict:
continue
event_sources.append(dict(
url=entry_dict["url"],
className=get_google_calendar_tag(entry_dict),
requireOnline=True))

from simplejson import dumps
return request.respond(
dumps(event_sources),
mimetype="text/plain")

def http_calendar_data(self, request):
start = float(request.GET.get("start", 0))
end = float(request.GET.get("end", 0))
Expand Down Expand Up @@ -946,6 +1015,7 @@ def http_calendar_data(self, request):
def http_get_all_js(self, request):
all_js_filenames = [
"jquery.js",
"jquery-migrate.js",
"jquery.timers.js",
"jquery.bgiframe.js",
"jquery.dimensions.js",
Expand Down Expand Up @@ -974,35 +1044,31 @@ def http_get_all_js(self, request):
mimetype="text/javascript")

def http_get_tag_color_css(self, request):
tags = request.dbsession.query(Tag).filter_by(name=u"colorconfig")

if request.GET.get("calendar", "") == "true":
pattern = """.tag-%(tag)s, .fc-agenda .tag-%(tag)s .fc-event-time, .tag-%(tag)s a
is_calendar = request.GET.get("calendar", "") == "true"
if is_calendar:
pattern = """.tag-%(tag)s, .fc-agenda .tag-%(tag)s .fc-event-time, .tag-%(tag)s .fc-event-inner
{ background-color: %(color)s; border-color: %(color)s; }"""
else:
pattern = ".tag-%(tag)s { background-color: %(color)s; color:white; }"


if tags.count():
color_config_tag = tags.one()

from sqlalchemy.sql import select
qry = select([request.datamodel.itemversions],
from_obj=get_current_itemversions_join(request.datamodel)) \
.where(ItemVersion.tags.any(id=color_config_tag.id))

import re
color_rule_re = re.compile(r"^\s*(?:\*\s+)?([a-zA-Z0-9]+)\s*:\s*(.*)$",
re.MULTILINE)
color_decls = []
for item_ver in request.dbsession.query(ItemVersion).from_statement(qry):
for match in color_rule_re.finditer(item_ver.contents):
color_decls.append(pattern % dict(
tag=match.group(1), color=match.group(2)))

css = "\n".join(color_decls)
else:
css = ""
color_decls = []
for entry_dict in self.get_config_info_by_tag(
request.datamodel, request.dbsession, u"colorconfig"):
for tag, color in entry_dict.iteritems():
color_decls.append(pattern % dict(tag=tag, color=color))

if is_calendar:
for entry_dict in self.get_config_info_by_tag(
request.datamodel, request.dbsession, u"googlecalendar"):
if "color" in entry_dict:
color_decls.append(
""".%(tag)s, .fc-agenda .%(tag)s .fc-event-time, .%(tag)s .fc-event-inner
{ background-color: %(color)s; border-color: %(color)s; }"""
% dict(
tag=get_google_calendar_tag(entry_dict),
color=entry_dict["color"]))

css = "\n".join(color_decls)

return request.respond(css, mimetype="text/css")

Expand All @@ -1026,4 +1092,6 @@ def serve_static(self, request, filename):

return request.respond(data, mimetype=mimetype)

# }}}

# vim: foldmethod=marker
5 changes: 4 additions & 1 deletion synoptic/html.py
Expand Up @@ -35,14 +35,16 @@ def calendar_page(context):
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html>
<head>
<title>Synoptic Mobile Calendar</title>
<title>Synoptic Calendar</title>
<link rel="stylesheet" type="text/css" href="static/jquery-ui-css/smoothness/jquery-ui-1.8.9.custom.css" media="screen"/>
<link rel="stylesheet" type="text/css" href="static/fullcalendar.css"/>
<link rel="stylesheet" type="text/css" href="static/calendar.css" />
<link rel="stylesheet" type="text/css" href="tag-color-css?calendar=true" />
<script type="text/javascript" src="static/jquery.js"></script>
<script type="text/javascript" src="static/jquery-migrate.js"></script>
<script type="text/javascript" src="static/jquery-ui.js"></script>
<script type="text/javascript" src="static/fullcalendar.js"></script>
<script type="text/javascript" src="static/gcal.js"></script>
<script type="text/javascript" src="static/calendar.js"></script>
<link rel="icon" type="image/png" href="static/calendar-favicon.png"/>
</head>
Expand Down Expand Up @@ -438,6 +440,7 @@ def mobile_calendar_page(context):
<link rel="stylesheet" type="text/css" href="tag-color-css?calendar=true" />
<meta name="viewport" content="width=device-width, initial-scale=1">
<script type="text/javascript" src="static/jquery.js"></script>
<script type="text/javascript" src="static/jquery-migrate.js"></script>
<script type="text/javascript" src="static/jquery-ui.js"></script>
<script type="text/javascript" src="static/fullcalendar.js"></script>
<script type="text/javascript" src="static/mobile-calendar.js"></script>
Expand Down
6 changes: 3 additions & 3 deletions synoptic/static/calendar.css
Expand Up @@ -19,8 +19,8 @@
background: #ffff88 !important;
}

.calendar-now, .fc-agenda .calendar-now .fc-event-time, .calendar-now a
{ background-image: url("construction.png") ; border-color: black; }
.calendar-now, .fc-agenda .calendar-now .fc-event-time, .calendar-now .fc-event-inner
{ border-color: black; }

.calendar-now a
.calendar-now .fc-event-inner
{ background-color: yellow; background-image: none; border-color: black; color: black; }
39 changes: 27 additions & 12 deletions synoptic/static/calendar.js
@@ -1,18 +1,33 @@
var SIZE_DECREMENT = 100;

$(document).ready(function() {
var cal =$('#calendar');

cal.fullCalendar({
theme: true,
contentHeight: window.innerHeight-SIZE_DECREMENT,
events: "/calendar/data",
header: {
left: 'prev,next today',
center: 'title',
right: 'month,agendaWeek'
}
})
var cal = $('#calendar');

$.getJSON('/calendar/event_sources',
function(event_sources) {
var actual_event_sources = [];

for (var i = 0; i<event_sources.length; ++i)
{
var entry = event_sources[i];
if (!entry.requireOnline)
actual_event_sources.push(entry);
else
if (window.navigator.onLine)
actual_event_sources.push(entry);
}

cal.fullCalendar({
theme: true,
contentHeight: window.innerHeight-SIZE_DECREMENT,
eventSources: actual_event_sources,
header: {
left: 'prev,next today',
center: 'title',
right: 'month,agendaWeek'
}
})
});

$(window).resize(function() {
cal.fullCalendar('option', 'contentHeight',
Expand Down

0 comments on commit 41d7d43

Please sign in to comment.