(Due to Firewall issues, I will be showing this locally in class.)
Written in Javascript and Python using JQuery, JQueryUI and Django.
Features
Flag interesting content on the web by highlighting blobs of text on arbitrary web pages. Submit a thought and bucket into class discussion topics.
See what other students flagged. Submit your own thoughts on those as well.
What was hard
Finicky clicking interaction for opening and closing flagging widget. Sorting through the python/Django way of doing things.
What’s missing
- Widget needs to be incorporated into Chrome browser add-on.
- Real username lookup based on userID.
- Remembering what the “current user” bucketed the flag with respect to class discussion themes.
- Pulling down a subset of the flags for “this unique location on the web.”
Talking to the db code
Defining the Table
class flaggedItem(models.Model):
flagId = models.CharField(max_length=50)
userId = models.CharField(max_length=50)
machineId = models.CharField(max_length=50)
groupId = models.CharField(max_length=50)
flagTime = models.DateTimeField()
menuItemId = models.IntegerField()
parentMenuItemId = models.IntegerField(null=True)
mediaType = models.CharField(max_length=30, null=True)
linkUrl = models.CharField(max_length=2000, null=True)
srcUrl = models.CharField(max_length=2000, null=True)
pageUrl = models.CharField(max_length=2000, null=True)
frameUrl = models.CharField(max_length=2000, null=True)
selectionText = TruncatingCharField(max_length=5000, null=True)
editable = models.CharField(max_length=30, null=True)
domain = models.CharField(max_length=300, null=True)
title = TruncatingCharField(max_length=500)
createTime = models.DateTimeField(auto_now_add=True)
def __unicode__(self):
return self.domain + ': ' + self.title
class thought(models.Model):
thought = models.CharField(max_length=50)
pre = models.CharField(max_length=50)
post = models.CharField(max_length=50)
posted = models.CharField(max_length=50)
class theme(models.Model):
groupId = models.CharField(max_length=50)
theme = models.CharField(max_length=50)
class flags_x_users_x_thoughts(models.Model):
flagId = models.CharField(max_length=50)
userId = models.CharField(max_length=50)
groupId = models.CharField(max_length=50)
thought = models.ForeignKey(thought)
createTime = models.DateTimeField(auto_now_add=True)
class flags_x_users_x_themes(models.Model):
flagId = models.CharField(max_length=50)
userId = models.CharField(max_length=50)
theme = models.ForeignKey(theme)
eval = models.BooleanField()
createTime = models.DateTimeField(auto_now_add=True)
Getting the data
elif view == 'flagged':
# flaggings
from_db = flaggedItem.objects.using(settings.STOOP_READ_DB).filter(groupId=group).values("flagId", "flagTime", "createTime", "groupId", "selectionText")
flaggedItems = convert_queryset_to_json(from_db)
# Truncate fields, Format date
for item in flaggedItems:
item['ffTime'] = FancyDateTimeDelta(item['flagTime'].replace(tzinfo=None)).format()
thoughts = flags_x_users_x_thoughts.objects.using(settings.STOOP_READ_DB).filter(flagId=item['flagId']).select_related().values("thought__posted", "userId")
item['thoughts'] = convert_queryset_to_json(thoughts)
for thoughtsie in item["thoughts"]:
thoughtsie['ffTime'] = FancyDateTimeDelta(item['flagTime'].replace(tzinfo=None)).format()
themes = flags_x_users_x_themes.objects.using(settings.STOOP_READ_DB).filter(flagId=item['flagId']).filter(theme__groupId=item['groupId']).select_related().values("userId", "theme__id", "theme__theme")
item['themes'] = convert_queryset_to_json(themes)
# for thought in item['thoughts']:
# thought['thought'] = thought['thought'].thought
result['flagged'] = flaggedItems
result['thoughts'] = convert_queryset_to_json(thought.objects.all())
result['themes'] = convert_queryset_to_json(theme.objects.filter(groupId=group).values("id", "theme"))
Writing the data
var parlorserver = {
cfg : parlorprofile.server,
getJSON : function (path, callback) {
$.getJSON(this.cfg.domain + path, callback, function (e) { console.log(e); } );
},
postToBrowseService : function (type, content, jsonPlusProfile) {
var contentToSend = jsonPlusProfile ? this.wrapWithProfile(type, content) : content;
$.post(this.cfg.domain + this.cfg.csPath + "/?subtype=" + type, {subtype : type, content : contentToSend}, null);
},
wrapWithProfile : function (key, data) {
return $.toJSON({ "profile": parlorprofile.client, data: data});
}
};
def process_flagged(q, message):
data = json.loads(message.get_body())
profile = data['profile']
flagData = data['data']
fi = flaggedItem()
fi.machineId = profile['machineId']
fi.userId = profile['userId']
fi.groupId = profile['groupId']
fi.flagId = flagData['flagId']
fi.menuItemId = flagData['menuItemId']
fi.parentMenuId = int_or_none(flagData, 'parentMenuItemId')
fi.mediaType = unicode_or_none(flagData, 'mediaType')
fi.linkUrl = unicode_or_none(flagData, 'linkUrl')
fi.srcUrl = unicode_or_none(flagData, 'srcUrl')
fi.pageUrl = unicode_or_none(flagData, 'pageUrl')
fi.frameUrl = unicode_or_none(flagData, 'frameUrl')
fi.selectionText = unicode_or_none(flagData, 'selectionText')
fi.editable = unicode_or_none(flagData, 'editable')
fi.flagTime = dateutil.parser.parse(flagData['flagTime'], ignoretz=True)
fi.domain = unicode_or_none(flagData, 'domain')
fi.title = unicode_or_none(flagData, 'title')
try:
fi.save()
except MySQLdb.Warning:
print fi.userId, fi.selectionText
q.delete_message(message)
def process_userthoughts(q, message):
data = json.loads(message.get_body())
profile = data['profile']
thoughtData = data['data']
utt = flags_x_users_x_thoughts()
utt.userId = profile['userId']
utt.groupId = profile['groupId']
utt.flagId = thoughtData['flagId']
utt.thought = thought.objects.filter(id=thoughtData['thoughtId']).get()
utt.createTime = dateutil.parser.parse(thoughtData['when'], ignoretz=True)
try:
utt.save()
except MySQLdb.Warning:
print utt.userId, utt.flagId, utt.userId, utt.groupId, utt.thoughtId, utt.createTime
q.delete_message(message)
def process_userthemes(q, message):
data = json.loads(message.get_body())
profile = data['profile']
themeData = data['data']
utm = flags_x_users_x_themes()
utm.userId = profile['userId']
utm.groupId = profile['groupId']
utm.flagId = themeData['flagId']
utm.theme = theme.objects.filter(id=themeData['themeId']).get()
utm.eval = themeData['themeEval']
utm.createTime = dateutil.parser.parse(themeData['when'], ignoretz=True)
try:
utm.save()
except MySQLdb.Warning:
print utm.userId, utm.flagId, utm.userId, utm.groupId, utm.createTime
q.delete_message(message)
