Building a To-Do List Application

Build a to-do list web application using Catalyst Advanced I/O Function and Catalyst Data Store that enables you to note down tasks to be done and delete them after they are done.

Configure the Advanced I/O Function

Let's begin coding the to-do list application by configuring the function component.

The functions directory, in this case functions/to_do_list_function, contains:

We will be adding code in the index.js file. We will not be modifying the code of the configuration and dependency files.

The three APIs in index.js that handle the routing between the server and the Data Store are:

  • GET /todo: To obtain the to-do list items from the TodoItems table in the Data Store
  • POST /todo: To create and save a new list item in the Data Store
  • DELETE /todo: To delete a list item from the Data Store

We will be coding the index.js using the Express Node.js framework. To import the Express package in the code, you must install the Express dependencies in your system.

To install Express.js in your local machine, navigate to the function's directory (functions/to_do_list_function) in your terminal and execute the following command:

$ npm install express --save

This will install the Express module and save the dependencies.

This information will also be updated in the package.json file.

Let's code the index.js file now. You can use any IDE of your choice to work with the application's files.

Note: Please go through the code given in this section to make sure you fully understand it. We will discuss the architecture of the function and the client in the next section.

Copy the code given below and paste it in index.js located in functions/to_do_list_function directory and save the file.

  • View code for index.js

    Copied 
    var express = require('express');
    var app = express();
    app.use(express.json()); // This supports the JSON encoded bodies
    var catalyst = require('zcatalyst-sdk-node');
    
    //The GET API gets data from the TodoItems table in the Data Store
    app.get('/todo', function (req, res) {
    	var catalystApp = catalyst.initialize(req);
    	var data = [];
    	getToDoListFromDataStore(catalystApp).then(
    		notes => {
    			var html = "";
    			notes.forEach(element => {
    				//Creates a HTML for the list of items retrieved from the Data Store
    				html = html.concat('<li value="' + element.TodoItems.ROWID + '">' + element.TodoItems.Notes + '</li>');
    			});
    			res.send(html); //Sends the HTML data back to the client for rendering
    		}
    	).catch(err => {
    		console.log(err);
    		sendErrorResponse(res);
    	})
    });
    
    //The POST API sends data to persist in the TodoItems table in the Data Store
    app.post('/todo', function (req, res) {
    	console.log(req.body);
    	var catalystApp = catalyst.initialize(req);
    	var datastore = catalystApp.datastore();
    	var table = datastore.table('TodoItems');
    	var notesVal = req.body.item;
    	var rowData = {}
    	rowData["Notes"] = notesVal;
    	var insertPromise = table.insertRow(rowData);
    	insertPromise.then((row) => {
    		res.redirect(req.get('referer')); //Reloads the page again after a successful insert
    	}).catch(err => {
    		console.log(err);
    		sendErrorResponse(res);
    	});
    });
    
    //The DELETE API deletes the selected items from the Data Store
    app.delete('/todo:item', function (req, res) {
    	var id = req.params.item;
    	var catalystApp = catalyst.initialize(req);
    	let datastore = catalystApp.datastore();
    	let table = datastore.table('TodoItems');
    	let rowPromise = table.deleteRow(id);
    	rowPromise.then((row) => {
    		res.send(id);
    	}).catch(err => {
    		console.log(err);
    		sendErrorResponse(res);
    	});
    });
    
    //This function executes the ZCQL query to retrieve items from the Data Store
    function getToDoListFromDataStore(catalystApp) {
    	return new Promise((resolve, reject) => {
    		// Queries the table in the Data Store
    		catalystApp.zcql().executeZCQLQuery("Select * from TodoItems order by createdtime").then(queryResponse => {
    			resolve(queryResponse);
    		}).catch(err => {
    			reject(err);
    		})
    	});
    }
    
    /**
     * Sends an error response
     * @param {*} res 
     */
    function sendErrorResponse(res) {
    	res.status(500);
    	res.send({
    		"error": "Internal server error occurred. Please try again in some time."
    	});
    }
    
    module.exports = app;
    

The functions directory is now configured.