SchoolEval – Teacher Evaluations and Walkthroughs

Product Launch

CA-BOCES, an entity of the New York State education system, recently launched a product called SchoolEval. Our intentions were primarily to provide additional value to the 22 local districts we support. As of this school year, changes in education policy demand teacher and principal performance be more rigorously monitored, and the State has released standards by which such performance can be measured. However, the tools to be used to collect and manage evaluations are up to districts. SchoolEval provides the means for a school district to design its own forms and rubrics to satisfy these requirements.

Intended Use

We see two main types of evaluation forms being used here. To satisfy State requirements, lengthy performance evaluations must be done. These will take time to complete and will not be conducted frequently. But, to gather data for these larger evaluations, school principals often walk through classrooms to observe a teacher and make a few notes. Simple observation forms or checklists synchronized with offline capable mobile devices make this process very easy.

Organization Setup

SchoolEval, the web application, allows an organization to define both its meta structure as well as its physical structure. Depending on the size of an organization, it might make sense to think of it in terms of divisions and departments with various staff types that may fit into different places within the organization. Regions and buildings can also be defined in order to group staff or to keep track of where an evaluation takes place.

Evaluation Configuration

Also on the web end of things is the actual ability to create evaluation forms. SchoolEval allows you to set up custom answer choices and corresponding widgets. For example, a simple Yes/No answer option might be horizontal radio buttons. A 1-5 rating might be a slider widget. Ineffective/Developing/Effective/Highly Effective might work best as vertically stacked buttons. The actual evaluations themselves are divided by sections which contain any mix of questions and rubrics.

Evaluations can be designated to apply to specific staff types or be universal. Similarly, they can be restricted to one or more divisions/departments within the organization or remain global. Evaluator accounts can also be restricted to specific areas, so that the staff they can evaluate is dependent on who they should have authority over.

Technologies

At it’s core is a MySQL database. Sitting on top of this are two servers providing two different methods of access. The web app is built on the Yii Framework, a wonderful PHP framework we have used for several apps. The mobile app communicates through a Node.js server utilizing Persistence.js.

SchoolEval’s web application uses a fair amount of jQuery and jQuery Mobile for conducting evaluations. Even though this is intended for desktop use, the jQuery Mobile evaluation forms work perfectly well for this scenario and lead to a common experience in the performing of evaluations. The only other bit of web app technology worth mentioning is Angular.js. Angularjs provides the mechanism for actually building evaluation forms.

School Eval’s mobile application is built on jQuery/jQuery Mobile. Persistencejs provides client side storage through WebSQL, which it can synchronize with the server side database through a plugin. When the server is not accessible due to lack of WiFi access, the app continues working, storing new records until the next time it is online.

Packaging for the App Stores

Finally, to ship the mobile app in the Apple App Store or the Android Market, we are using a product called PhoneGap. This allows us to build a native application for each platform. PhoneGap is an amazing product that can give a JavaScript application access to devices features, such as GPS, accelerometer, camera, etc.

Posted in CA-BOCES | Leave a comment

Mobile Synchronization With Persistencejs

Over the last year, I developed a web application with a mobile client. I used the same PHP MVC framework I’ve built several other applications with, but the real learning came from the extensive use of JavaScript required for a cross-platform mobile application capable of being packaged for native distribution with PhoneGap.

In a nutshell, my application is about evaluation forms. You need to define your organization, your evaluators and your staff(evaluees). You then create custom forms with custom answer types and associate them with parts or all of your organization. The mobile app, upon login, pulls down all the records needed to be able to construct the forms on the fly in online or offline mode.

Given that I wanted to support both Android and iOS platforms with minimum development time and without having to learn a new language, I decided to rely on HTML5 and the WebSQL. jQuery Mobile was just coming out when we began our planning, so I knew I could use that for my interface. With WebSQL, I could save a large amount of information on the local device and enable the app to function offline. The challenge was going to be synchronizing my data with the server.

Data Storage

For the foundation of the app, the data storage component consists of a product called persistence.js, which abstracts the actual WebSQL interaction into a nice, clean object model.

// simple method for defining models
var Task = persistence.define('Task', {
    name : "TEXT",
    description : "TEXT",
    done : "BOOL"
});

// create new objects
var newTask = new Task();
newTask.name = "Task Name";
newTask.description = "Task Description";
newTask.done = false;
persistence.add(newTask);

// retrieval
Task.all().filter('done','=',true).list(function(tasks){ /***/ });

Synchronization

persistence.js works on the server side with node.js. I used it on top of a MySQL database. The model declarations are nearly identical to those on the client. A simple node app is required to handle the sync requests. This was accomplished using Connect and Express to provide a set of URIs for each model to sync with. The sync process works like this: first the client GETs updates, then it POSTs its own new records.

// client sync configuration
Task.enableSync('http://m.mydomain.com/taskupdates');

//server side URIs
app.get('/taskupdates', function(req, res) {
  persistenceSync.pushUpdates(req.conn, req.tx, Task,
      req.query.since, function(updates){
    res.send(updates);
  });
});

app.post('/taskupdates', function(req, res) {
  persistenceSync.receiveUpdates(req.conn, req.tx, Task,
      req.body, function(result){
    res.send(result);
  });
});

Multi-Customer Database

With persistence.js, it is simple to synchronize a WebSQL table with a MySQL table. It is powerful, but there was a huge problem when I started using it. My app is a service provided to many customers. The MySQL database contains sensitive information. I didn’t want a mobile device to hold records that belonged to a different customer. Also, in some cases, not all records needed to be pushed down to the client and only increased bandwidth usage. But there was no way to filter in persistence.js — it was all or nothing.

In the GET stage of the sync process, we call pushUpdates from the persistence.sync.server.js plugin with parameters for the Entity model and the client-passed “last-synced” variable. I worked with Zef Hemel, the creator of persistence.js, to add a subtle little change to this pushUpdates function that allows for custom filtering.

Here’s what pushUpdates looked like originally.

pushUpdates = function(session, tx, Entity, since, callback) {
  Entity.all(session).filter("_lastChange", ">", since).list(tx,
      function(items) {/***/});
};

After the change, you could pass the Entity model, which comes across as a “function” variable type. If, in your server code, you wanted to apply a number of filters to the model, you would have a Query Collection object.

pushUpdates = function(session, tx, Entity, since, callback) {
  var queryCollection;
  if(typeof(Entity) == "function"){
    queryCollection = Entity.all(session);
  }else if(typeof(Entity) == "object"){
    queryCollection = Entity;
  }
  queryCollection.filter("_lastChange", ">", since).list(tx,
      function(items) {/***/});

In the GET request on the server side, you can generate a query collection before you move call pushUpdates. If you know the client’s customer id, you can use that to filter.

For example, if our Task entity had a customer_id field.

Task = persistence.define('Task', {
  name : "TEXT",
  description : "TEXT",
  done : "BOOL",
  customer_id : "INT"
});

If you had the customer_id stored in the session, when the client requested updates, you could filter a query collection before calling pushUpdates.

app.get('/taskupdates', function(req, res) {
  var queryCollection = Task.all(req.conn)
      .filter('customer_id','=', req.session.customer_id);
  persistenceSync.pushUpdates(req.conn, req.tx, queryCollection,
      req.query.since, function(updates) {
    res.send(updates);
  });
});

TL;DR

Discrete mobile synchronization of database tables between a client and a multi-customer database is now made easy with the persistence.js library.

Posted in Javascript | Tagged , , | Leave a comment

Todo Example with Angularjs and Persistencejs

In the world of JavaScript frameworks, it appears the Todo app has become the new Hello World. I came up with the idea a while ago seemingly on my own, because I thought it would make a nice, easy to understand way to showcase the particular stack of libraries I have been using. Perhaps it is the collective consciousness, but as I started working on my demo, I noticed a few others doing the same.

Tobias Bosch and Christoph Burgdorf have both been working with Todo examples using the angular.js library which I have recently fallen in love with. Then came Addy Osmani, who runs a slick website/web-dev ninja training academy. Addy came up with the brilliant idea to package a number of demos from various JavaScript MVC frameworks all based around the same design. Naturally, the demo of choice was Todo.

Addy used Christoph’s Angularjs app in his TodoMVC package. I forked TodoMVC and made a copy of the Angularjs example. I added to this example a service which stores the todo list in a local database in the browser using persistence.js.

In a nutshell, Angularjs works by binding html elements with a JavaScript controller. The controller holds the data objects that are linked to html as well as any methods that may be triggered by the webpage. Controllers can be enhanced by injecting services, which supply specific additional functionality.

Persistencejs is a framework that provides an abstraction layer for local storage in the browser. I have been using it to create WebSQL databases for mobile projects. It also has a plugin for synchronization through Node.js.

My change to the Angularjs Todo example was to add a service which wrapped all the Persistencejs functionality. The example still works the same, but any time you add, edit or remove items, it makes an additional call to the Persistencejs service. Additionally, when first loaded, the controller is able to fetch any locally stored items to pre-populate the page.

The working demo can be viewed here: http://jacobmumm.com/demos/todo/. Below, I are some highlights of the changes.

First, it was necessary to create an Angularjs service to handle the Persistencejs calls. The way Angularjs services are defined is in the singleton pattern. The constructor is a factory that produces a usable object, and it is during this time that I can setup the local database.

This is what the service looks like.

angular.service('persistencejs', function() {
	persistence.store.websql.config(persistence,
 'todo', 'todo database', 5*1024*1024);
	var Todo = persistence.define('todo', {
		content: 'TEXT',
		done: 'BOOL'
	});
	persistence.schemaSync();
	return {
                //singleton containing all methods to be called
        };

The controller is now declared with a parameter, expecting the service to be injected afterward.

App.Controllers.TodoController = function (persistencejs) {/*...*/};
App.Controllers.TodoController.$inject = ['persistencejs'];

Within the TodoController, methods can now properly call methods in the persistencejs service:

//in TodoController:
  self.addTodo = function() {
      if (self.newTodo.length === 0) return;

      self.todos.push({
          content: self.newTodo,
          done: false,
          editing: false
      });
      //below is the only change I made to this method
      //I only need to know the content, because
      //it can be assumed new items are not done yet
      persistencejs.add(self.newTodo);

      self.newTodo = "";
  };

//in the persistencejs service:
add: function(item){
	var t = new Todo();
	t.content = item;
	t.done = false;
	persistence.add(t);
	persistence.flush();
},

One critical caveat I must mention here applies to the situation where Angularjs data gets modified asynchronously. If you modify data within controller methods, the automatic data binding will trigger the page to be refreshed. However, this is not the case when the data gets updated asynchronously. Persistencejs is an asynchronous library, so every interaction happens this way. Fortunately, there is a simple solution. Anytime you have made such asynchronous manipulations, you simply need to call the $apply method on your controller.

Posted in Javascript | Tagged , | Leave a comment