MarkUs Blog

MarkUs Developers Blog About Their Project

Archive for the ‘Notes System’ Category

New Notables

without comments

The other evening I worked on the New Notes page.

The current one (left) deals only with Groupings. First you select the assignment, and then you select the grouping that you want to write the note about. It dynamically updates the Groupings drop down with the associated group names when you select an Assignment.

This is very good behaviour!

The task I set for myself was to extend this type of thing to our new noteables, Assignments and Students.

One way about it would be to have a separate form link for each type, before getting to the proper form. That has the downside of requiring additional page loads and then you need to start back at the hub page if you change your mind about what you want to write notes about.

The approach that I’m taking is to have an additional drop box where you first select the Notable type, and the rest of the form changes as required to select the exact object you want to create the note on. This way, less page loads, and hopefully, less work for me, as I don’t wish to refactor the entire notes system for a minor bit of convenience.

What convenience and I talking about? Well, it’s entirely possible to write a completely general system that automatically creates the form I want whenever we add the notable property to a model. However, that would take me longer than I have left in the term to do properly, and further isn’t really necessary. Such a solution would be the epitome of the Rails DRY philosophy.

It’s not a good idea though. When adhering to a philosophy involves more work than the less elegant but simpler solution, it’s not the solution you want to implement.

So my approach will be thus: have a static list of notable types and partials forms we want to render. We have one partial form for each, and whenever we observe the Notables box changing, we use a little bit of AJAX magic to render the new part of the form.

With that said, let’s see what we have now:


<div id="title_bar"><h1><%=I18n.t('notes.new.title')%></h1></div>
<div>
<% form_for :note, :url => {:action => 'create'} do |f| %>
<%= f.error_messages %>
<fieldset>
<p>
<%= f.label :assignment_id %>
<%= select_tag "assignment_id", options_from_collection_for_select(@assignments, :id, :short_identifier),
\:onchange => remote_function(:url => { :action => 'new_update_groupings' },
:with => 'Form.Element.serialize(this)',
:before => "Element.show('loading_groupings')",
:success => "Element.hide('loading_groupings')") %>
</p>
<p>
<%= f.label :noteable_id, "Grouping" %>
<%= f.select :noteable_id, @groupings.collect {|p| [p.group_name_with_student_user_names,p.id]} %>
<span id="loading_groupings" style="display:none">
<%=image_tag('spinner.gif')%> <%=I18n.t('notes.new.loading_groupings')%>
</span>
</p>
<p>
<%= f.label :notes_message %>
<%= f.text_area :notes_message, :rows => 10 %>
</p>
</fieldset>
<%= f.submit I18n.t('save') %>
<% end %>
</div>

The basic structure is what you’d expect. It creates a form object, and then builds the form in the way you want it to later display. The user can select things, type up a note, and get the end result no problem. Heck, the user can even start writing a note, change the assignment and grouping it’s onand not have to start writing their note over again! That’s slick!

What I want to do is extract out the mechanism to select the noteable object from the form. This isn’t too hard. The selection boxes are what’s the same so I just need to put  those first two things into a file I called _grouping.html.erb . Here’s what it looks like:


<p>
<%= f.label :assignment_id %>
<%= select_tag "assignment_id", options_from_collection_for_select(@assignments, :id, :short_identifier),
\:onchange => remote_function(:url => { :action => 'new_update_groupings' },
:with => 'Form.Element.serialize(this)',
:before => "Element.show('loading_groupings')",
:success => "Element.hide('loading_groupings')") %>
</p>
<p>
<%= f.label :noteable_id, "Grouping" %>
<%= f.select :noteable_id, @groupings.collect {|p| [p.group_name_with_student_user_names,p.id]} %>
<span id="loading_groupings" style="display:none">
<%=image_tag('spinner.gif')%> <%=I18n.t('notes.new.loading_groupings')%>
</span>
</p>

Note that nothing is different from when those lines were in the original file. Then I add one bit of rails magic to replace the lines I removed:


<%= render :partial => 'grouping', :locals => {:f => f} -%>

This line of code does two things. First: it retrieves the partial file I just created, in this case for the Groupings. Second: it passes in the form object we created. That part is important since it allows us to modify the form in the partial, as we need to.

Visually, this produces nothing different. It’s identical to what we saw before. Now for the tricky bit.

A few hours of writing, experimenting and testing later, having gone so far as having it generate Javascript that would be treated as values in the dropdown and then a generic function that dealt with each case, then to the final result here…

You can now select the type of notable!The tricky bit is getting it so we can select the kind noteable we want to write a Note for, and be able to retrieve the right partial, while getting the parts of the form in the partial to work properly. Getting behaviour like this isn’t too hard, but getting it to be reasonably generic and easy to extend is.

The noteables we have right now are fairly straight forward and the two we are adding require only one drop down for selection. We could just replace the list in the dropdown with some RJS magic, and hide the assignment selector when we aren’t selecting a Group.

The problem with that approach is we have separate sets of cases to deal with, and we have to ensure they all work when testing and adding new ones. Also, we have more things to look out for if we want to change how we are selecting the object (ie. filtering Students by Section, rather than a single list of Students). By dealing with all cases uniformly, we reduce the opportunity for error.

The end result for the business bits of the new note form is as follows:


<p>
<%= f.label :noteable_type, I18n.t('notes.noteable')%>
<%= select_tag "noteable_type", options_for_select(Note::NOTEABLES) %>
<%= observe_field :noteable_type, \:on => 'onchange',:url => {:action => :noteable_object_selector},
:with => "noteable_type",
:before => "Element.show('loading_selector')",
:success => "Element.hide('loading_selector')" %>
<span id="loading_selector" style="display:none">
<%=image_tag('spinner.gif')%> <%=I18n.t('notes.new.loading_selector')%>
</span>
</p>
<div id="noteable_selector">
<%= render :partial => 'grouping' %>
</div>

A few things have changed.  We now have a selector that choses between a list of Noteables that I put in the Notes model. Whenever the user changes the selected value, I call this ‘noteable_object_selector’ function in the controller, and flash this little loading box so the user knows that something is reacting to their selection. There is also that “noteable_selector” div towards the bottom that renders the partial for Groupings as default.

The ‘noteable_object_selector’ is actually an RJS call. RJS is a handy mechanism Rails provides to return snippets of Javascript that get executed by the browser immediately when received, usually to do a bit of DOM manipulation, but generally anything that you can get Javascript to do. Here’s what it looks like.



page.replace_html 'noteable_selector', :partial => params[:noteable_type].downcase


It’s sheer elegance in its simplicity! All it does is generate Javascript that replaces the contents of our “noteable_selector” div with the contents of the desired partial. There’s a little bit before that gets the required entries from the DB in the controller, but that’s so we have something to display in the dropdowns in the partials, rather than being magic to explain.

The astute reader will have noticed that I don’t have that “:locals => {:f => f}” bit at the end of the line like I had in the first step. How did I get around not having the form object anymore? The answer is simple. Rails provides exactly a mechanism to get around that. Here’s the partial for selecting Students to demonstrate. The partial for Assignments and Groupings are similar.


<% fields_for :note, :url => {:action => 'create'} do |f| %>
<p>
<%= f.label :noteable_id, "Student" %>
<%= f.select :noteable_id, @students.collect {|p| [p.user_name,p.id]} %>
</p>
<% end %>

The fields_for function does exactly the same thing as form_for except that it doesn’t generate the <form> tags, permitting exactly the behaviour I was aiming for with the locals parameter. We just wrap whatever partial we might want to use as parts of the form in a fields_for and it will generate form elements compatible with the form that we set it up for. Very handy!

Now we have a solution that is relatively simple to extend to new noteables as well as change how noteable objects are selected if we like. Everything is dealt with equally, which is important for testing since we don’t have special cases to deal with.

Written by Robert B

March 16th, 2010 at 11:35 pm

Posted in Notes System

The Plan for Notes

with 2 comments

For the past few hours I’ve been diving deep into the Notes system to find out exactly what needs to be changed in order to be able to add notes to all of Groupings (status quo), Assignments, and individual Students.

From the previous post on the subject:

We have completed the first three steps, including unit and functional tests. Thanks to the polymorphic, “noteable” idea that we used for the relationship between a note and a grouping, the only work necessary to have notes on a different object type is to:

  • add a “display_for_note” method to the model, like we did for groupings – this allows us to display these notes
  • modify the create a note form in the Notes tab to allow for other types of noteable objects than just groupings
  • add a link to the modal dialog in an appropriate location for the object type

For now, I can’t see the best place to place a link to a modal dialog to create a note associated to an assignment or to a student, so I would recommend just adding that functionality to the Notes tab.

This leads me to believe that most of the work is cut out for me. Which as near as I can tell, it is!

I’ll endeavour to break up my changes as mentioned above, described below:

  1. Low Hanging Fruit – a simple isolated change to add the display_for_note functionality, and associated tests, to the models of Assignments, and Groupings. Also, the notes main page will need to be updated to not have the add_new when there are no ‘noteable’ objects in the DB at all, rather than simply groupings, as it is now.
  2. Refactor Note Creation page – Once the other objects are able to be “noted” the next place to change is the main notes creation page. Currently it’s designed to look solely for Groupings that we can apply notes to. It will need to be updated with a drop down of the types, and then dynamically update a subsequent drop box with those types. This will be much clearer than simply putting all notable objects into a single drop box, even though it adds another pair of clicks to creating a note from scratch.
  3. Adding Modal Dialog links to Assignments and Student pages – These will be put in sensible locations, probably adjacent to the edit link in the student table, and on both the Assignment main table page, and the assignment configuration page. We don’t want to confuse people by having ambiguous Notes links without being clear what the noteable object is.

For 3 I’ll need to consult with Victoria for best placement of the links, as this is a usability issue, first and foremost.

Change 2 is also a usability issue somewhat, but I can’t think of a simpler solution interface wise than two drop downs in the create note page.

One issue that should be interesting to deal with is the case of Single student groups. Do we apply the note to the grouping as we do now? Or would it be better to apply it to the student in that group? The obvious solution is to do nothing, and use locality to decide. Whenever a note is being created in marking an assignment of a single student, the most likely intention of the user is to make a note on the grouping, as it’s related to the assignment. Otherwise, they would seek to make a note on the student specifically either in the table of students, or in the Note creation form in the Notes tab.

Input on this plan would be much appreciated, though I won’t be able to answer detailed technical questions until I’m arm deep into the code.

Written by Robert B

February 16th, 2010 at 2:56 pm

Posted in Notes System

Notes system: what’s left to do

with one comment

This post was originally written at the beginning of December 2009 and I just found it now, so I’m publishing it 🙂

Our original steps for the Notes system implementation went as follows:

  1. Design the model.
  2. Create mock-ups of the user interface.
  3. In parallel, design the Notes tab and the modal dialog interfaces (for groupings).
  4. Extend this functionality to assignments and to students once the notes system is solid for groupings.

We have completed the first three steps, including unit and functional tests. Thanks to the polymorphic, “noteable” idea that we used for the relationship between a note and a grouping, the only work necessary to have notes on a different object type is to:

  • add a “display_for_note” method to the model, like we did for groupings – this allows us to display these notes
  • modify the create a note form in the Notes tab to allow for other types of noteable objects than just groupings
  • add a link to the modal dialog in an appropriate location for the object type

For now, I can’t see the best place to place a link to a modal dialog to create a note associated to an assignment or to a student, so I would recommend just adding that functionality to the Notes tab.

Written by Tara Clark

January 26th, 2010 at 5:41 am

Posted in Notes System

Notes Modal dialog

with 3 comments

This is the modal dialog for the notes system. I stole the idea from review board and just change it a little bit.

One thing that i am planning to do but I couldn’t right now was to put the username in bold.

This dialog is going to be available in the assignment-> groups & graders view and in the submission view of the graders

notes view1

Written by fgarces

November 11th, 2009 at 2:57 pm

Posted in Notes System

Notes model

with 8 comments

This is the model that we are planning to use for the notes system.

We are going to relate the notes to the users that created them and for the groupings that they are assigned to.

Since we are focusing first on doing notes only for groupings the type column won’t be used, but if time permits we will use it to be able to add notes on submissions or assignments.

Depending on what we decide on foreign keys, we will have to add indexes for user_id and groupings_id to increase performance.

Notes DB

Written by fgarces

November 4th, 2009 at 3:23 pm

Posted in Notes System

Notes system mock-ups

with 3 comments

I am proposing a possible aggregate view of all notes to be placed on a new tab called “Notes”, displayed to the right of the existing tabs in the list. This tab would only be visible to graders and to admins.

Next to the header on the page, we would put an icon allowing the user to add a new note, which would bring up a modal dialog similar to the ones that Fernando is going to mock up. I picked this location because on the Users pages, there is an “Add New” link in small text next to the title.

The main attraction is the table with the notes in it. After playing around with a couple of more table-like looks, I settled on this one that looks more like messages. There are three columns in each row. The first indicates data in the following format:

[username] on <b>[assignment short identifier]:  [comma-separated student usernames]</b>

<small>[full date] at [time]</b>

The second column shows the full text of the note and the third column shows edit and delete icons, if the current user has the privilege of doing so. (Admins can edit/delete all notes and graders can edit/delete notes that they created themselves.)

Each row will be highlighted in grey when hovered over.

Using the “on” method of indicating the object the note is for makes this view much more flexible when we add further objects that we can note on other than just groupings. For a grouping, we would show the assignment short identifier and all of the student memberships. But for an assignment, we would simply show its short identifier or for a student, its username.

Notes tab

Written by Tara Clark

November 4th, 2009 at 3:17 pm

Posted in Notes System

Notes System: Initial Design

with 4 comments

At the code sprint, we tossed around some ideas for the “Messages between TAs and instructors” feature that Karen asked for. Today, I’ve been brainstorming what I think this feature should look like, functionally.

Feature goal

To allow small pieces of information to be left on various aspects of the course, pertaining to something specific, to alert others to the problems (or good things!), with a timestamp. These could potentially pertain to an assignment, a student, or a grouping, or we could limit these to just one of these types.

Example uses

If students are suspected to be cheating, then the grader could “flag” the assignment for the instructor by leaving a note. Since other graders can also see it, then they can see that this student was previously flagged for cheating. If the student is sick and gets an exemption on part of the assignment, then a note could be placed on the affected assignment for the grader to take that into account during marking.

Can anyone think of other potential uses of this feature?

Where to create these?

Now that we have some idea of how this could be used in a real course – it’s always key to keep the users in mind – we need to think about where in the work flow we would want to create these pieces of information.

While marking an assignment, we should be able to make notes. These would be noted against the grouping, since this encompasses assignments where the students work alone, as well as assignments where the students work together and keeps in mind the idea that one student having a problem can affect all students in the grouping. It also allows us to have notes go against a single object, since a grouping represents an assignment as well as the students working on it.

We should also be able to make a comment about a particular student in general or about a a particular student on an assignment, not from the marking view. Should we also be able to comment about an assignment? This could be incorporated into the viewing of the comments described below.

Replies

What about replies to a comment? Should we incorporate these into our feature? I think that we shouldn’t at this time, since the initial idea is for more one-off ideas, but I think that the model should be designed in a flexible enough way such that we can have multiple notes against the same object, which would allow for multiple notes to be left against an object and thus “replies” of a sort without complicating the model too much.

Where to view these?

I propose adding a new tab in the menu for Admins and Graders, with its text being the name we decide upon for this feature. In here, we can display all of the messages (paged in case there are a lot of them?) and have a link to add new ones as well. Would distinguishing the new comments made since last login from the previous ones be useful? You should be able to sort the view. You should also be able to filter it by assignment or by student ID (which would obviously return all comments left against that student, as well as comments left against any groupings it is a member of).

Model

At the code sprint meeting, someone suggested modifying the annotations model for these notes, but that idea was declined since we don’t want to relate these to the code. The conclusion was that we will need a new model to represent these ideas.

The pieces of information that we need to store are: the user who wrote the note, the timestamp from when it was written, the object ID that it is against, the type of object it is against (grouping, student, assignment, etc.), and the actual text of the note itself.

Naming

We need to consider how we’re going to name this feature. Several initial possibilities come to mind: Messages, Notes, and Comments. (I actually found all three of these used interchangeably in my notes from the Sunday code sprint meeting!)

  • I don’t like the term “Messages” because it implies that they are sent from one person to another, which these won’t be – they’ll be available for viewing by all instructors AND graders. I do, however, like its implication that these are being shared with other people.
  • The term “Comments” is too close to the ideas of commenting code and the overall comments on an assignment that are shared with the students. I think that a new term is in order to ensure that information is not left in this field that the students shouldn’t see.
  • My favourite is definitely the term “Notes” because it implies that these are small pieces of information, pertaining to something specific. It doesn’t carry the connotation that it is just between specific individuals, so it is much more fitting than “Messages”.

I am definitely open to suggestions on other names or further comments on the names that I have suggested.

Anything else?

Are there any other pieces related to this feature that I haven’t outlined? I look forward to hearing your ideas about the upcoming notes feature in MarkUs!

Written by Tara Clark

October 17th, 2009 at 10:47 pm

Posted in Notes System

Tagged with