Archive for the ‘Usability’ Category

React is a JavaScript library for building user interfaces. It’s used heavily in production in both Facebook and Instagram (Facebook created React), and in my opinion is an awesome tool for building front-end interfaces.

The work I’m currently doing on MarkUs involves re-implementing, using React, the sortable, searchable, and filterable tables used for listing users and managing groups, graders, and submissions. This is a prime target because 1) the previous tables used a library that depended on Prototype, which we are trying to move away from, 2) these tables can be really slow, since the html for each row is rendered in the backend individually, and 3) the previous tables became messy enough (_boot.js.erb files and construct_xxx_table_row methods) to warrant a rewrite. Also because 4) React is awesome. So let’s go into how React works.

React, at its core, is a library for creating components: functional, reusable, and composable web views. It also manages to let you do this in an extremely simple fashion.

Each component has two objects: this.props and this.state. Props are generally for holding immutable data, while state holds mutable data. In a sortable table, for example, the titles of the columns would go into props and the currently sorted column and sort direction would go into the state. A component then defines a render method that is functionally pure; that is, given the same props and state, the output will always be the same. The render method also cannot cause any side effects.

Now, when React detects a state change of any kind, it’ll quickly re-render diffs for the new DOM based on the render method. Managing state suddenly got a lot easier.

Here’s an example from MarkUs: StudentsTable, which is the React component that defines the listing of students in the Users view. StudentsTable has two pieces of state: students, which is the array of student data that will be used to fill the table, and selected_students, which is an array of student ids that represent the selected students (duh) for doing actions on.

The render method then defines some column and filter objects (based on an ad hoc protocol; column objects have boolean attributes such as sortable and searchable while filter objects define a test for each object). Then it returns a div (really a React DOM object: React uses a virtual DOM) containing two other components: an ActionBox and a Table.

Here’s some demo code for StudentsTable:

StudentsTable = React.createClass({

getInitialState: function() {

// Sets this.state.students to

// what the backend returns

jQuery.ajax({

method: 'GET',

url: ...

dataType: ...

success: ...

});

},

render: function() {
// this stuff could and maybe should actually be moved to props

Now, StudentsTable will pass down selected_students to ActionBox, which will receive it as props. This may be a little confusing since selected_students was in state originally, but it doesn’t matter. ActionBox doesn’t know, and ActionBox doesn’t care. Its render function should account for both state and props, and in fact it helps to think of selected_students as immutable, since what ActionBox really needs to be worrying about are things like the dropdowns and the grace credits input and managing that stuff.

We can see that the data flow is kept one-way: StudentsTable, as the parent of the ActionBox, doesn’t know about the state of the ActionBox, nor does it care. If you really needed to know something, like when StudentsTable should request new data, you can create a hook by passing down the refresh method as a prop and have ActionBox call it whenever it needs to. But in general, it’s best to keep upward data flow as minimal as possible.

The base Table is its own component with its own subcomponents like TableFilter, TableSearch, and TableHeader which may or may not have their own subcomponents. But these parts all work in the same way; they’re just smaller parts. This way, React makes reasoning about a specific level in the view hierarchy a lot simpler since everything is compartmentalized and data flows only one way. Consider implementing the same thing in jQuery or Prototype: it would probably require a crazy amount of reasoning about state (of which the size is huge — blame combinatorial explosion) and DOM manipulation.

In conclusion: React is dope. Its power comes from its means of combination and abstraction (sup Sussman). Check it out here.

What’s C.R.A.P?

Contrast

Different elements (titles, heading, body text, etc.) must look different from each other. This can be achieved by varying fonts, line thickness, colours, shapes, sizes, space, etc.

Repetition

Repeat an aspect of the design throughout the website, for example all titles will use the same font, size, weight, etc. This makes the website consistent.

Alignment

Don’t place elements arbitrarily on the page. Elements of the same importance should be aligned vertically and horizontally.

Proximity

Group related elements together, for example a heading should be closer to the text it belongs to than to the text of the previous paragraph. Physical close elements imply a relationship.

C.R.A.P at MarkUs

The Problems

Dashboard

The dashboard is overall fine. there small problems with the alignment of the assignment information.

Assignments

On the main page the proximity was violated when the class average was equally close to both assignments.It should be closer to assignment 1 and farther from assignment 2. It was also directly under the assignment. It is part of the assignment therefore it should be under the details of the assignment. The rounding is also different then the one on the dashboard. All pages should follow the same rounding rules.

The submission page has options right next to the name of the assignment. While they should be underneath. The options for sorting the table were using completely different style, using buttons rather than text as the options above them. I would suggest changing all the options to look like buttons. There is the rounding issue again.

On the groups page the options for each student are at different place depending on the length of the name. They all should be in the same place right underneath each other. The tabs for managing groups should be on the same line, if there is no space then at least the search should be on a separate line then the tabs.

Annotation

The annotation page the Help is the same size of the assignment title. They should be different size and style since they are different things. The options are directly next to the title. They should be underneath and changed to buttons.

Grading

On the Grading page The previous and next submission are higher than the rest of the options for some reason. They should be vertically aligned. Same applies to the check box for released. For unreleased assignments under the summary is a complete mess. There are issues with alignment and proximity. Most of the things there are done with tables but then it just stopped and things got out of alignment.

Users

The options on this page are all of a sudden on the right and not next to title like on other pages. This breaks the repetition between pages.

Student

On the student view the assignment rules are completely different than the rest of the section. Also all the details there are on the same line while the message is underneath. This is inconsistent.

The Pictures

The Good

Over all there is good contrast through out the website. The website is pretty consistent about its’ layout and there is pretty good proximity.

User preferences will soon be added to the Assignment->Submissions page and here is a little overview of what to expect.

Entries per page, Sort order

The number of entries per page and the sort order (column name, asc/desc) will now be saved after the user sets them. Those settings are user/assignment dependent, therefore they can be set independently when the user/assignment change.

Show/hide columns

The user will be able to change which columns are shown/hidden via a pop-up triggered by clicking the pencil at the end of the table’s header (see picture below). Those settings will only be user dependent (for a specific page), therefore, if the user chooses to hide a specific column, this column will remain hidden for all the assignments’ submissions this specific user sees.

Cookies

For the moment, independent cookies are created for every setting saved as a preference. As an example, the show/hide columns preference is stored in the cookies as “[userId]_submissions_columns”. The number of entries per page is stored in the cookies as “[userId]_submissions_[assignmentId]_sort_by”. Therefore, you can test individual cookies/setting more easily.

There are multiple ways to save cookies:

1: cookies[(cookie name)] = “Cookie content”

This will create a temporary cookie which will be deleted when the user’s browser is closed.

2: cookies.signed[(cookie name)] = “Cookie content”

This will create a temporary cookie which will be deleted when the user’s browser is closed. A signed cookie can’t be tempered with manually by users. The cookie is signed with a unique app token.

3: cookies.permanent[(cookie name)] = “Cookie content”

This will create a permanent (20 years) cookie. If the user chooses to clear his browser’s cookies, those will still be deleted.

4: cookies.permanent.signed[(cookie name)] = “Cookie content”

This will create a signed permanent cookie. If the user chooses to clear his browser’s cookies, those will still be deleted.

User preferences are currently saved in unsigned permanent cookies (#3).

Tips & Tricks

In Chrome, you can easily see all your cookies in a “user readable” way:

In the main menu (top-right, next to the URL bar), click Settings.

Scroll down, click “Show advanced settings”.

Under Privacy, click “Content settings…”.

Under Cookies, click “All cookies and site data…”.

You can then search all your cookies by entering the desired host name. If you enter “localhost”, you should see all the cookies your local Markus creates. You can then choose one and see all its content/metadata.

This can be very useful when you need to debug/develop using unsigned cookies (signed cookies are not user readable). I don’t know if Firefox offers something similar though.

Final word

There would probably be better ways to handle single/multiple cookies (maybe with a specific gem). If any of you have any ideas regarding user preferences, don’t hesitate and let me know! I will probably be working on implementing them for other pages, so it will not be difficult to change some aspects while I’m at it.

The developers of MarkUs use GitHub’s issue tracking system to handle all the bugs floating around our application. It is a very useful system for maintaining current and old bugs, requests for new features and represents the overall state and goals of MarkUs.

Unfortunately, our users do not have the chance to see this unless they try hunting it down themselves. I’m currently working on a feature to point our users to our bug tracker, providing them with easy access to the ability to view and report bugs at their convenience. Here is some sample UI that I’m brainstorming. I’ve come up with some rough drafts of UI that I will most likely use.

The Header

I’d like to add an icon that is placed in the header, providing users with access to it no matter which page they are viewing.

The Popup

Once the icon is clicked, a modal dialog will open, disabling the rest of the webpage. The user will see the following options.

View current issues will point to the bug tracker. Reporting a new issue will point them to a blank issue form and requesting a new feature/enhancement will point to the same form but with the RFE label set already. All of these links will open new tabs and redirect to our tracker accordingly.

Drawbacks

In order to file issues, you will need to have a GitHub account. Users might not be bothered to sign up (or even sign in), making this feature practically useless to them. Unfortunately, there is not much we can do with our given resources. Forcing them to use our tracker will help keep things centralized and in one place, rather than setting up some kind of form that sends out emails to mailing lists with the given bugs. Fortunately, the links redirect to logging in or creating a new account and then redirect back once done. If the user is willing to follow through, the login process is just a small, extra step and places the user back on track.

Another issue is the potential increase in duplicate bugs. Some people do not have time to read through our current issues and may just jump straight to reporting one. This is not too disruptive but adds to a teadious process for developers now having to close duplicate issues. I am hoping that the “View current issues” link will nudge users in that direction first but that will not always happen.

Finally, some issues are not in the application but in the way it was setup. These need to be directed to the course admin rather than to us. However, this is not always obvious so adding this feature might also cause an overflow of unnecessary bugs. This can be avoided by only displaying the links in the dialog when the user is an admin. When a grader or student is logged in, perhaps a simple message telling them to contact their course administrator/instructor might suffice.

This is what I have come up with but I am open to suggestions, please nitpick, modify and comment away!

Here is the UI for Role Switching that I developed. I made the design to be similar to that of the login screen though there were some changes. The changes I made was just so that the UI for role switching is not confused for that of logging in.

The option to switch roles added for admins to the top right of the screen

The UI for role switching added to the right of the screen

The view of the UI in the browser

The screen displayed after the admin with first name “admin” switches role to student c5anthei

Error Messages:

The error messages are a mirror of the ones for login

Error message displayed when user name and password fields are blank

The password field was blank

The user name was invalid

Input about the quality of the work and some error cases that I might not have considered will be appreciated.

Hora and I have been experimenting with a number of possible options for graphing data in MarkUs. We have narrowed down our options to two javascript frameworks and are going to use this blog post to solicit input from the Markus community.

Highcharts

Highcharts is a commercial javascript graphing library. However, they have released their software under a creative commons license for use in non-commercial projects. Additionally, lazy_high_charts is a rails plugin which allows for simple integration of highcharts into rails projects.

Samples

Pros

Thanks to lazy high charts, most of the programming can be done in the controller. This leads to cleaner code.

Graphs are very attractive, animations are professional.

Dynamically hide single items in a chart. Example, don’t show one of the TAs.

Lots of options for creating charts

Great documentation

Cons

Built on JQuery. Markus uses Prototype which can have conflicts with JQuery. In the few tests we’ve done several javascript errors were reported.

As a commercial product, we are unsure about the future possibilities for use. Licenses can change.

Bluff

Bluff is a JavaScript port of the Gruff graphing library for Ruby. It is pure javascript and has no conflicting dependencies.

Samples

Pros

Small javascript files, with no dependence on JQuery.

Easy to generate graphs quickly.

MIT License, so no conflicts with Markus.

Simple, attractive graphs.

Cons

Code must be written in Javascript. This means that most of the work will be done in the view, which creates ugly code. If we choose this path, a set of ruby helper methods (or a rubygem) could be created to clean up the code.

More simplistic than Highcharts.

API exists, but doesn’t provide a lot of examples.

Conclusions

Both graphing methods work well. Highcharts produces a cleaner code base but has some implementation issues and is (sort of) proprietary. Bluff is completely open source but will involve embedding javascript into views (or partials). If anyone has opinions either way please sound off in the comments.

I have been working on making MarkUs more accessible, particularly to blind users. To help me with this goal I installed a free open source screen reader, NVDA. I plan on using other screen readers and technology in the future as well as working with blind users.

To begin with, the screen reader is really fun, but after navigating for sometime you start to get frustrated with the length of time that it takes to do some things, and the voice gets annoying too. I can see why people who use screen readers all the time make the voice go so fast, you want to be able to listen to everything as fast as you could read it visually.

After working with MarkUs for a few days in this format, here are some key features for accessibility that I need to work on, and which other developers should keep in mind when working on user interfaces:

Everything has to be accessible using the keyboard only! This is the only input method that we can assume everyone will be able to use. The biggest problem with this in MarkUs is the accordion menus, they are only accessible through the mouse. We will have to either get rid of them or make it so that they can be navigated to using the keyboard. Another problem is dragging and dropping for reordering things, this is really convenient with the mouse and should not be removed, but we should add alternative buttons for keyboard access.

Focus is a problem, especially with javascript making new boxes and windows appear. When these things appear the focus remains where it was before, and when you are using only a screen reader it seems like nothing happened. For things like the upload file window, the box that seems to be in front of everything else on the screen is actually at the end of the document, so you have to tab through a lot of things until you see that something new has actually appeared. If we could automatically change the focus when something like this appears, that would be a lot of help, and it would probably help everyone else too.

Every form input element should have a label! We are pretty good at doing this so far, but there are places here and there where there is text that describes the form element, but is not formatted as a label. It’s pretty easy to change this text into a label and it really helps to identify what each element does, otherwise you just hear something like “checkbox unchecked” and have to go hunt for the text that labels it. There are some places where having a label does not make sense for sighted users (like in a table of students, we don’t want to have a label beside each checkbox) but we can make hidden labels in this case for the benefit of people who don’t see the visual association.

Overall we have already done a good job of making things accessible just by following web conventions well, and if we deal with the points I mentioned above then I think MarkUs will be doing well accessibility-wise. The next step is to work with someone who actually requires the use of a screen reader, and I’m sure I will learn a lot more about what we could do to make things better!

I am using the wiki page as a way to keep track of progress for myself, look there for more specific details.

As per last week’s UI/UX meeting, I’ve made changes to the first draft of the group formation tab wireframes:

Group Formation: Adding a student to a group

Group Formation: Removing a student from an existing group

Group Formation: Filtering -- Only show valid group formations

Group Formation: Filtering -- Only show invalid group formations

These prototypes will be used in a simple usability session where we will be getting preliminary usability feedback from a small sample of our current users. More feedback and updates on these prototypes are to come.

These prototypes will also be discussed in tomorrow’s UI/UX meeting in our IRC channel, #markus. Please join us if you can make it! 🙂

Section A: Project-wide

Description: To replace the current accordion menu upload/download options with upload and download buttons running along the top of the view. Let’s call these “Action Buttons”.

Next Steps:

These action buttons will spawn a modal dialogue (similar to the interface we currently have for adding a new student to a group in the Groups & Graders view), where the user can specify the location of the CSV file to upload or download.

To avoid confusion and maintain consistency, will have to apply this migration throughout the entire project.

Rationale: Having the accordion menu on the side will greatly affect the readability of the 2-pane Assign Graders view. Also, the accordion menu has caused confusion amongst users in the past, so switching to modal dialogues may improve the usability of MarkUs as a whole.

Topic A2: Reorganize Action Links & Action Buttons

Note: “Action Links” refer to the action items to the right of the page header located at the top of every view.

Description: Current prototype inherits action links from the existing release of MarkUs. However, if we were to replace the accordion menu with action buttons running along the top of the view (right-to-left), these may interfere with the existing action links we already have running from the left to the right.

Next Steps: Compile a list of action links and buttons that we will have for each view. Analyze the list and see how we can categorize, trim down, or reorganize the layout of these options.

Rationale: As mentioned in the description, the left-to-right action links may potentially interfere with the right-to-left action buttons.