Sunday, June 26, 2011

GSoC 2011 Integration with External APIs: Learning new tools - W5

This week i was busy with fixing my patches. Madhusudan suggested me a tool to create mutable changesets : Mercurial Queues (aka MQ). It was  not possible to work on multiple commits without actually commiting them. This great extension makes this possible. You can create a patch, edit it, then create new one and return back to previous patch to edit it. (Patch is a mutable changeset) I benefit from this mostly in two ways : First as i am new to community my commits need to be reviewed. When i send a patch for review, i can start to work on another while first one is in review and mutating. Second reason which also will make me use MQ even after i'm good enough to send my commits without review is it helps divide and code! I can divide a job into parts which are slowly growing (each part corresponds to a commit). So i have a working job which is not complete but each parts are still growing and making working job better. Instead of finishing each part in order and trying to make them perfect as i dont have chance to go back, i'm working on every task at the same time synchronously. I also wrote on my Turkish blog about MQ :)

Another tool i was introduced was {{less}} which helps writing CSS in a hierarchical style, without requiring to write full selector path for each block. It also allows defining variables which prevents redundancy when using same values multiple times. It's clearly more programmers way to CSS.

While being little late for proposal syncing feautre. I still could find some time to think on it and send a mail to community to discuss on it. There is no harm to copy/paste my current idea here :)

  • When user goes to '.../proposal/submit...', represent a sub-page with two buttons : Edit HTML, Sync with GDocs
  • Go to a different page for each selection, each represents different form. (e.g. '/proposal/submit/gdocs', '/proposal/submit/default') One page requires to login GDocs and a gdocs flag will be True for proposal entity after saved. 
  • For updating part, 'edit proposal' link's destination will be changed with regards to proposal's gdocs flag (either go to '/proposal/update/gdocs/id' or '/proposal/update/default/id').
  • Widget 'GDocs Link' will have a 'sync now' button near it. When user pastes link to field and presses "sync now" button, an ajax request will be executed. Text area 'Content' (which is not editable) will be updated with result of that AJAX request. So actually, in server-side, we won't process document link again and treat form like its content edited by hand. 

GCI 2011 GCI with New Architecture

Hello all !!

This week I have worked on the views after completing the conversions tasks.I first started off with RedirectHelper for constructing redirects in GCI.Each of the methods in this helper returns the RedirectHelper object after setting certain parameters like _no_url, url_name, _url, args and kwargs.The clear method clears the current internal state and urlOf method returns the resolved url for name using current internal state for args and kwargs.At this stage certain field from GSoCProgram like about_page, events_page, events_frame_url, connect_with_us_page etc are required for GCI too and hence they are moved up to soc.models.program.Program.The RequestData patch for GCI got reviewed and I am about to commit it now after making a couple of changes.
I then proceeded to the Access Checker for GCI.For this not much is needed at the moment and more methods will be added as we move on with the views.For now, I have to written a couple of methods one is access_checker.Mutator.taskFromKwargs which sets the task entity in the RequestData object and the other is access_checker.AccessChecker.isTaskInURLValid to check if the task in the url exitst or not.After acess_checker I have moved onto site menus for GCI.I was told that I can use the same site menus as that of GSoC for now.So I went ahead and have written a smiliar site menus for GCI which contains siteMenuContext to generate URL links for the hard-coded GCI site menu items and Header, MainMenu and Footer templates.I have then finally moved onto RequestHandler for GCI.The render method of the soc.views.base.RequestHandler is overridden to extend the context object with header, mainmenu and footer values which are rendered Templates for the current RequestData object.I have now started with the Task view.

GSoC 2011 GUI Overhaul: The Admin View's Design

Hi everyone,

From my previous post I've talked about colorbox approach for admin dashboard. If you want to try, visit my demo instance at http://melange-new-dashboard.appspot.com/ using the following account:

password: melangetestdashboardpassword

There are some changes in the JS, CSS and template. Some of these were just new files. I'll talk about code that make a sense to review. Before that, I'll divide the topic into two sections so you can skip a topic that you don't want to read.

Changes in admin's view

If you've tried the admin dashboard from the link that I gave above. You should try to toggle the colorbox or click the "Program settings" link. If you click the "Program settings" link, the dashboard will change its content. The case is the same for "Manage organizations" link. If you inspect the page with firebug, you'll notice that it just switching between div elements. Let's call this a sub dashboard.


So, a link that have sub links at the bottom of its description will point to the div that hidden at that moment, that's a sub dashboard. When we clicked "Program settings", the div with id "program-settings-dashboard" will be shown, the "disabled" class was removed. And the "main-dashboard" will be hidden. I figured out what's the best solution to reorder the links or reorganizing sub dashboard without coupled too many files. So I came up with the idea that these links and sub dashboards should be managed inside soc.modules.gsoc.views.admin. I managed to create a new class named Dashboard that inherits Template class:

class Dashboard(Template):
"""Base dashboard for admin page
"""

def __init__(self, request, data, subpages=None):
"""Initializes the dashboard.

Args:
request: The HTTPRequest object
data: The RequestData object
subpages: Subpages of current dashboard
"""
self.request = request
self.data = data
self.subpages = subpages

def getSubpagesLink(self):
"""Returns the link to other dashboard that appears
on top of the dashboard.
"""
return self.subpages

def templatePath(self):
"""Returns the path to the template that should be used in render()
"""
return 'v2/modules/gsoc/admin/dashboard.html'

def _divideSubPages(self, subpages):
"""Returns the subpages divided into two columns.
"""
middle_ceil = int(math.ceil(float(len(subpages))/2))

return [
subpages[:middle_ceil],
subpages[middle_ceil:],
]

Currently there are three dashboards that inherits Dashboard class, they are: MainDashboard, ProgramSettigsDashboard and ManageOrganizationsDashboard. To get you the clear idea, here's the MainDashboard and ProgramSettigsDashboard classes:

class MainDashboard(Dashboard):
"""Dashboard for admin's main-dashboard
"""

def __init__(self, request, data):
"""Initializes the dashboard.

Args:
request: The HTTPRequest object
data: The RequestData object
"""
super(MainDashboard, self).__init__(request, data)

def context(self):
"""Returns the context of main dashboard.
"""
r = self.data.redirect
r.program()

manage_orgs = ManageOrganizationsDashboard(self.request, self.data)
program_settings = ProgramSettigsDashboard(self.request, self.data)

subpages = [
{
'name': 'lookup_profile',
'description': ugettext(
'Lookup profile of mentor or student from various program.'),
'title': 'Lookup profile',
'link': r.urlOf('lookup_gsoc_profile')
},
{
'name': 'allocate_slots',
'description': ugettext(
'Allocate slots (number of acceptable projects) per '
'organization'),
'title': 'Allocate slots',
'link': r.urlOf('gsoc_slots')
},
{
'name': 'slots_transfer',
'description': ugettext(
'Transfer slots for organizations'),
'title': 'Slots transfer',
'link': r.urlOf('gsoc_admin_slots_transfer')
},
{
'name': 'duplicates',
'description': ugettext(
'Calculate how many duplicate proposals'),
'title': 'Duplicates',
'link': r.urlOf('gsoc_view_duplicates')
},
{
'name': 'manage_organizations',
'description': ugettext(
'Manage organizations from active program. You can allocate '
'slots for organizations, manage invitations for '
'org admin/mentors, and withdraw/accept students/mentors '
'from various organizations'),
'title': 'Manage organizations',
'link': '',
'subpage_links': manage_orgs.getSubpagesLink(),
},
{
'name': 'reminder_emails',
'description': ugettext(
'Send reminder emails for evaluations.'),
'title': 'Send reminder emails for evaluations',
'link': r.urlOf('gsoc_survey_reminder_admin')
},
{
'name': 'program_settings',
'description': ugettext(
'Edit program settings and timeline'),
'title': 'Program settings',
'link': '',
'subpage_links': program_settings.getSubpagesLink(),
},
{
'name': 'participant_locations',
'description': ugettext(
'Show all participants (students and mentors) in a '
'clusterer map. You can also view a single profile map '
'after clicking the marker.'),
'title': 'Participant Locations',
'link': '#'
},
{
'name': 'report_statistic',
'description': ugettext(
'Reports and statistics of program'),
'title': 'Report/statistic',
'link': '#'
},
]

return {
'title': 'Admin Dashboard',
'name': 'main',
'subpages': self._divideSubPages(subpages),
'enabled': True
}


class ProgramSettigsDashboard(Dashboard):
"""Dashboard for admin's program-settings-dashboard
"""

def __init__(self, request, data):
"""Initializes the dashboard.

Args:
request: The HTTPRequest object
data: The RequestData object
"""
r = data.redirect
r.program()

subpages = [
{
'name': 'edit_program',
'description': ugettext(
'Edit your program settings such as information, slots, '
'documents, etc.'),
'title': 'Edit program',
'link': r.urlOf('edit_gsoc_program')
},
{
'name': 'edit_timeline',
'description': ugettext(
'Edit your program timeline such as program start/end date, '
'student signup start/end date, etc.'),
'title': 'Edit timeline',
'link': r.urlOf('edit_gsoc_timeline')
},
]

super(ProgramSettigsDashboard, self).__init__(request, data, subpages)

def context(self):
"""Returns the context of manage organizations dashboard.
"""
subpages = self._divideSubPages(self.subpages)

return {
'title': 'Program Settings',
'name': 'program_settings',
'backlink': {
'to': 'main',
'title': 'Admin dashboard'
},
'subpages': subpages
}

To set the links, we need to set it into subpages context. If you want a link to another dashboard inside MainDashboard, such as "Program Settings", just create another class that inherits Dashboard, supply the backlink to refer back to the parent's dashboard and set the subpages of its own dashboard inside the new class. In the parent dashboard's subpages context supply the subpage_links to indicate this is a dashboard link. How about the icon itself? This is where the CSS rules. The name you supply for each link inside the subpages content will be rendered as a class name of the link's container. Everything's that related to the style of admin dashboard is defined inside v2/gsoc/admin.css file. I got the icons from Tango Desktop Project which is licensed under GPL.

The next thing that you might need to know is the addition of colorbox base layout. A colorbox base layout is minimalistic template without sidebarmenu and header. The rest is the same. To make any page rendered in colorbox layout, you need to pass cbox query string. The RequestHandler will take care the base layout. Each page that extends the base.html template need to change the extends tag to base_layout, {% extends base_layout %}. The rest of changes inside soc.modules.gsoc.views.admin were new handlers with list.

What's done and what needs to be done or in-progress

I promised to finish the admin dashboard before the mid-term. This means the code it self should be reviewed lately in this week. The scope for the deadline before the mid-term was a fully functional admin dashboard that the mockup already given before. Okay, here are what's done in the admin dashboard:

  • New admin's view architecture that I've discussed in the previous section
  • Handling colorbox template
  • A few handlers inside soc.modules.gsos.views.admin

Here are what needs to be done and in-progress:
  • Submit my code for review, possibly after writing this post.
  • The test_slots was failed because I created new template and changed the list template for accepted organizations. I refactor the list for accepted organizations inside admin's view so other handlers can use it. I'll fix the test after my code being reviewed.
  • Adding test for soc.modules.gsoc.admin. By looking at other view tests, it just a test case to make sure the template is rendered with the right context.
  • A participant locations to mark all participant into a single map using MarkerClusterer. This is not a critical requirement and can be skipped.
  • Refined toggleable list patch as suggested by Mario.