Flagarrific: Social browsing for large lecture classes.

(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)
This entry was posted in Dynamic Web Dev, Projects. Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>