Building a Simple Web Application

Create a single-page serverless web application using Catalyst Advanced I/O Function and Catalyst Data Store that allows you to report or look up alien encounters in a city.

Configure the Client

Now, let's configure the client component. The client directory contains:

  • The index.html file that contains the HTML code for the front-end application
  • The main.css file that contains the CSS code for the front-end application
  • The main.js file that contains the JavaScript code
  • The client-package.json configuration file

We will be coding index.html and main.js.

Note: Please go through the code in this section to make sure you fully understand it.

Copy the code below and paste it into the respective files located in the client/ directory of your project using an IDE and save the files.

  • View code for index.html

    Copied 
    <!DOCTYPE html>
    <html>
    
    <head>
        <meta charset="utf-8" />
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <title>AlientCityAppClient</title>
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <link rel="stylesheet" type="text/css" media="screen" href="main.css" />
        <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css"
            integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
        <script src="https://code.jquery.com/jquery-3.4.1.min.js"
            integrity="sha256-CSXorXvZcTkaix6Yvo6HppcZGetbYMGWSFlBw8HfCJo=" crossorigin="anonymous"></script>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js"
            integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous">
        </script>
        <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js"
            integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous">
        </script>
        <script src="main.js"></script>
    </head>
    
    <body>
        <br>
        <br>
        <center>
            <h1>ALIEN CITY</h1>
        </center>
        <div class="container">
            <ul class="nav nav-tabs" id="myTab" role="tablist">
                <li class="nav-item">
                    <a class="nav-link active" id="check-tab" data-toggle="tab" href="#check" role="tab"
                        aria-controls="check" aria-selected="true">Check My City</a>
                </li>
                <li class="nav-item">
                    <a class="nav-link" id="report-tab" data-toggle="tab" href="#report" role="tab" aria-controls="report"
                        aria-selected="false">Report Alien Encounter</a>
                </li>
            </ul>
            <div class="tab-content" id="myTabContent">
                <div class="tab-pane fade show active" id="check" role="tabpanel" aria-labelledby="check-tab">
                    <br>
                    <br>
                    <form>
                        <div class="form-group">
                            <label for="city-get-input"><b>Check if your city has aliens:</b></label>
                            <input type="text" class="form-control" id="city-get-input" aria-describedby="checkCity"
                                placeholder="Enter City Name">
                        </div>
                        <button type="submit" class="btn btn-primary"
                            onclick="getAlienEncounter();return false;">Check</button>
                    </form>
                    <br>
                    <br>
                    <div id="result-container">
                        <div id="result-text">
                        </div>
                        <br>
                        <div id="result-image">
                        </div>
                    </div>
                    <div id="loader" style="display: none;">
                            <div class="spinner-border" role="status">
                                <span class="sr-only">Loading...</span>
                            </div>
                        </div>
                </div>
                <div class="tab-pane fade" id="report" role="tabpanel" aria-labelledby="report-tab">
                    <br>
                    <br>
                    <form>
                        <div class="form-group">
                            <div class="city-post-input">
                                <label for="exampleInputEmail1"><b>Enter the name of the city where you encountered an alien:</b></label>
                                <input type="text" class="form-control" id="city-post-input" aria-describedby="cityPost"
                                    placeholder="Enter City Name">
                            </div>
                        </div>
                        <button type="submit" class="btn btn-primary"
                            onclick="postAlienEncounter();return false;">Report</button>
                    </form>
                </div>
            </div>
        </div>
    </body>
    </html>
    
  • View code for main.js

    Copied 
    /* 
      * Fires an API call to the server and adds the reported city as an alien city
      */
    function postAlienEncounter() {
        var city = $("#city-post-input").val();
    
        // Fires an Ajax call to the URL defined in the index.js function file
    // All URLs to the Advanced I/O function will be of the pattern: /server/{function_name}/{url_path}
        $.ajax({
            url: "/server/alien_city_function/alien", //If your Advanced I/O function is coded in the Java environment, replace the "alien_city_function" with "AlienCityAIO"
            type: "post",
            contentType: "application/json",
            data: JSON.stringify({
                "city_name": city
            }),
            success: function (data) {
                alert(data.message);
            },
            error: function (error) {
                alert(error.message);
            }
        });
    }
    
    /**
     * Fires an API call to the server to check whether the given city is alien city or not
     */
    function getAlienEncounter() {
        showLoader();
        var positive = "https://media.giphy.com/media/Y1GYiLui9NHcxVKhdo/giphy.gif";
        var negative = "https://media.giphy.com/media/fsPcMdeXPxSP6zKxCA/giphy.gif";
        var city = $("#city-get-input").val();
    
      // Fires an Ajax call to the URL defined in the index.js function file
     // All URLs to the function will be of the pattern: /server/{function_name}/{url_path}
        $.ajax({
            url: "/server/alien_city_function/alien?city_name=" + city, //If your Advanced I/O function is coded in the Java environment, replace the "alien_city_function" with "AlienCityAIO"
            type: "get",
            success: function (data) {
                console.log(data);
                $("#result-text").text("");
                $("#result-text").text(data.message);
                var imagesrc = negative;
                if (data.signal == 'positive') {
                    imagesrc = positive;
                }
                $("#result-image").html("");
                $("#result-image").html("<img src='" + imagesrc + "' />");
                hideLoader();
            },
            errror: function (error) {
                alert(error.message);
            }
        });
    }
    
    function showLoader()
    {
        $("#result-container").hide();
        $("#loader").show();
    }
    
    function hideLoader()
    {
        $("#loader").hide();
        $("#result-container").show();
    }
    
Note: The Node.js function's name alien_city_function has been added in the code for main.js in the lines 10 and 37. If you created the Advanced I/O function in the Java environment, you must replace the Node.js function's name with the Java function's name. Please replace it with AlienCityAIO in the code as indicated by the comments.

The client directory is now configured.

Let us quickly go through the working of the function and client components of the application:

  1. GET operation
    • When you enter a city name in the client to check for a record of previous alien encounter, the onClick event for the Check button in index.html triggers the getAlienEncounter() function defined in main.js.
    • This fires an Ajax call to the URL route defined in the Advanced I/O function. The GET API defined in AlienCityAIO.java or index.js then invokes the getDataFromCatalystDataStore function and passes the request query.
    • This function searches for the data in the AlienCity table in the Data Store by executing a ZCQL query.
    • If a record matching the city name is found in the table, a positive signal is sent as the response. Otherwise, a negative signal is sent as the response.
    • The client then displays the message that matches the response. A GIF matching the response defined in main.js is also displayed.
  2. POST operation
    • When you enter a city name in the client to report an alien encounter, the onClick event for the Report button in index.html triggers the postAlienEncounter() function defined in main.js.
    • This fires an Ajax call to the URL route defined in the Advanced I/O function. The POST API defined in AlienCityAIO.java or index.js then invokes the getDataFromCatalystDataStore function and passes a request query to check if a record with the same city name already exists.
    • This function searches for the data in the AlienCity table in the Data Store by executing a ZCQL query. If the record already exists, a response is sent which enables the client to display an appropriate message to the user.
    • If there are no records for the city name, a new row is created in the AlienCity table for the city name entered by the user. A pop-up box is displayed in the client confirming the insertion of the record in the Data Store. An appropriate message is also pushed to the logs which can be checked from Logs under the Monitor section in the console.