KendoUI DataSources + Dropbox DataStore: Read


Few days ago, on September 25th 2013, Dropbox announced Dropbox Datastore API stable release (see it here).

Also, Couchbase has recently announced as part of their effort on bringing NoSQL databases to mobile devices their strategy of JSON anywhere.

This post is about the first: Dropbox DataStore; and I will show you how to save data in Dropbox.

Dropbox DataStore

I’m assuming that you already have a Dropbox account and have downloaded Dropbox following their instruction. If not, drop me some lines and I will help you on how to set it up.

In the blog what I’m going to save is the data for a Grid and supporting Create, Read, Update and Delete operations. This is based on their example and it will look like:

Screen Shot 2013-10-11 at 23.45.51

DataSource Grid definition

The code for the Grid is pretty standard:

$("#grid").kendoGrid({
    dataSource: taskTableDS,
    columns   : [
        { field: "taskname", width: 80 },
        { field: "created", format: "{0:G}", width: 200 },
        { field: "completed", width: 70 }
    ]
});

As you can see there is nothing fancy and all you need to do is in the DataSource where we will have to map KendoUI DataSource into Dropbox DataStore.

But before start reading data from Dropbox DataStore, you need to do some little initialization that identifies you and the DataStore that you are going to use.

Dropbox DataStore initialization

// Insert your Dropbox app key here:
var DROPBOX_APP_KEY = '0sh............';

// Exposed for easy access in the browser console.
var client = new Dropbox.Client({key: DROPBOX_APP_KEY});

// Try to finish OAuth authorization.
client.authenticate({interactive: true}, function (error) {
    if (error) {
        alert('Authentication error: ' + error);
    }
});

This is all you need but remember to keep your DROPBOX_APP_KEY as secret as it needs to be since otherwise you can get other people saving their data in your Dropbox.

Now, we can start using via client Dropbox API.

Reading Data from Dropbox DataStore into Kendo UI DataSource

Kendo UI DataSource will be something like:

var taskTableDS = new kendo.data.DataSource({
    transport: {
        read   : function (op) {
            // Read Task from Dropbox
            readTasks(op);
        }
    },
    schema   : {
        model: {
            id    : "id",
            fields: {
                id       : { type: "string" },
                taskname : { type: "string" },
                created  : { type: "date", editable: false },
                completed: { type: "boolean" }
            }
        }
    }
});

Where I push all the intelligence into readTasks that looks like:

function readTasks(op) {
    if (client.isAuthenticated()) {
        // Client is authenticated.
        var datastoreManager = client.getDatastoreManager();
        datastoreManager.openDefaultDatastore(function (error, datastore) {
            if (error) {
                alert('Error opening default datastore: ' + error);
            }
            taskTable = datastore.getTable('tasks');
            var records = taskTable.query();
            op.success(records);
        });
    }
}

If our application (Dropbox client) is actually authenticated agains Dropbox, we get a handler for accessing the DataStore Manager (use getDatastoreManager) and we start opening the default DataStore (openDefaultDatastore).

NOTE It is important to note that this function starts but takes some time to get finished since it needs to got to Dropbox servers for getting the information.

Then we set taskTable with the content of the DataStore table tasks and use query for retrieving the desired information. Since I do not set any condition, I retrieve all records.

For sending this information to Kendo UI DataSource, I invoke op.success with the records retrieved.

BUT Kendo UI DataSource format is not compatible with Dropbox DataStore. There are some small -but important- changes that prevent a direct mapping between both structures.

What we need to do is convert Dropbox DataStore into Kendo UI DataSource and I do this defining a parse function in my model.

parse: function (d) {
    var res = [];
    $.each(d, function (idx, elem) {
        res.push(parseItem(elem));
    });
    return (res);
}

This parse function, receives as argument the data that I retrieved when execute query. So this is directly invoked upon op.success(records); done in readTasks. Then iterates over all records and builds a res array with the result of parsing each item (which I do in parseItem).

parseItem is:

function parseItem(elem) {
    return {
        id       : elem.getId(),
        taskname : elem.get("taskname"),
        created  : elem.get("created"),
        completed: elem.get("completed")
    };
}

You can see that each record property is retrieved using get except the id that requires using getId.

NOTE: If you use get and set in a Dropbox item you actually get an attribute called id but do not retrieve / update the id of the actual record.

So, what we have looks like:

// Insert your Dropbox app key here:
var DROPBOX_APP_KEY = '0sh............';

// Exposed for easy access in the browser console.
var client = new Dropbox.Client({key: DROPBOX_APP_KEY});
var taskTable = null;

// Try to finish OAuth authorization.
client.authenticate({interactive: true}, function (error) {
    if (error) {
        alert('Authentication error: ' + error);
    }
});

function parseItem(elem) {
    return {
        id       : elem.getId(),
        taskname : elem.get("taskname"),
        created  : elem.get("created"),
        completed: elem.get("completed")
    };
}

function readTasks(op) {
    if (client.isAuthenticated()) {
        // Client is authenticated.

        var datastoreManager = client.getDatastoreManager();
        datastoreManager.openDefaultDatastore(function (error, datastore) {
            if (error) {
                alert('Error opening default datastore: ' + error);
            }
            taskTable = datastore.getTable('tasks');
            var records = taskTable.query();
            op.success(records);
        });
    }
}

var taskTableDS = new kendo.data.DataSource({
    transport: {
        read   : function (op) {
            readTasks(op);
        }
    },
    schema   : {
        model: {
            id    : "id",
            fields: {
                id       : { type: "string" },
                taskname : { type: "string" },
                created  : { type: "date", editable: false },
                completed: { type: "boolean" }
            }
        },
        parse: function (d) {
            var res = [];
            $.each(d, function (idx, elem) {
                res.push(parseItem(elem));
            });
            return (res);
        }
    }
});

$("#grid").kendoGrid({
    dataSource: taskTableDS,
    columns   : [
        { field: "taskname", width: 80 },
        { field: "created", format: "{0:G}", width: 200 },
        { field: "completed", width: 70 }
    ]
})

And this is all you need for a read-only connection between Kendo UI DataSource and Dropbox DataStore.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s