Generating a Simple Report with jsreport and express.js: The Lazy Way

xavier_script

Onwuka David

Posted on July 20, 2024

Generating a Simple Report with jsreport and express.js: The Lazy Way

Ever heard of the term "lazy programmer"? πŸ¦₯:) I recently heard that being one is actually a good thing. You may ask why. Well, It is actually not so difficult to understand.

A "lazy programmer" is a term often used humorously to describe a programmer who strives to achieve maximum efficiency with minimal effort. The idea is that by being "lazy," they focus on writing clean, maintainable, and reusable code to avoid repetitive tasks.

That is the idea here. You need to quickly generate a report using jsreport? Then this article is for you.

What you'll need

To follow up with this tutorial, you'll need these:

  • Latest version of Node.js and npm installed on your computer

  • A basic knowledge of HTML, CSS, and Javascript

  • A basic knowledge of Express.js

You are sure you've met the requirements above? Let's go then.

Installing jsreport

So first, we'll need to install and configure jsreport. Head over to https://jsreport.net
Click on "Download" and you'll be taken to their download page.

You'll notice that there are popular platforms installation manuals which you can follow depending on the platform you are using. For this tutorial, we are going to be using Windows, so click on the Windows icon and let's start the installation process.

Go to the command prompt on your desktop and type this to create a folder called "jsreportapp"

mkdir jsreportapp

Then we move into that folder by typing this on the command prompt:

cd jsreportapp

Next, we install jsreport:

npm i -g @jsreport/jsreport-cli

This command will install the jsreport service for you to use on the already created "jsreportapp" folder.

Next command to run would be one to initialize jsreport in your app:

jsreport init

We are now going to run a command to configure the jsreport service according to our needs:

jsreport configure

This will pop up some questions for you to answer. Your answers should depend on what you are using the service for. Since we are trying to create a quick report generating service, We're going to make things as simple as possible. πŸ˜‰
See a snapshot below of what we are working with. Feel free to customize yours according to your preferences.

Some Commands

Now, we finish our installation process by running this command:

jsreport start

Now you should be able to open a browser and reach your jsreportapp locally on the port you set for yourself earlier. In this case, it is going to be at: http://localhost:5488

Building a local server

For this, our basic knowledge of Express.js would be really useful. To create a local server, head over to the command prompt and run this:

mkdir my-express-app
cd my-express-app
npm init -y

The command above creates a new directory for your local server, navigates into that directory and runs "npm init" to create a package.json file. You can accept the default settings or customize them as needed.

Next we install Express:

npm install express

Having installed express, open your folder with your preferred code editor, create a file called "index.js" and add up the code below to set up your basic express server:

import express from "express";

const app = express();
const port = 3000;

app.get('/', (req, res) => {
  res.send('Hello, World!');
});

app.listen(port, () => {
  console.log(`Server is running on http://localhost:${port}`);
});

Enter fullscreen mode Exit fullscreen mode

Notice that the code above uses ES6 modules instead of Commonjs. So you may want to resolve this before moving on.

Afterwards, start your express server by running the following command in your terminal:

node index.js

You should see a message indicating that the server is running. Open your browser and go to http://localhost:3000 to see the "Hello, World!" message.

Generating a report

Now we are going to generate a simple downloadable html report. To do this, we create a "public" folder in our "my-express-app" folder. In the public folder, we then create an "index.html" file. So head over there and paste this simple report template:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <style>
      body {
        font-family: Arial, sans-serif;
      }
      .report {
        max-width: 800px;
        margin: 0 auto;
        padding: 20px;
        background-color: #f9f9f9;
        border: 1px solid #ddd;
        box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
      }
      h1,
      h2,
      h3 {
        color: #333;
      }
      p {
        line-height: 1.6;
        margin-bottom: 10px;
      }
    </style>
  </head>
  <body>
    <div class="report">
      <h1>Monthly Report</h1>
      <p>This is a simple HTML report template.</p>

      <h2>Summary</h2>
      <p>
        Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec malesuada
        magna eu libero lacinia ultrices.
      </p>

      <h2>Details</h2>
      <ul>
        <li>Item 1: Description of item 1</li>
        <li>Item 2: Description of item 2</li>
        <li>Item 3: Description of item 3</li>
      </ul>

      <h2>Conclusion</h2>
      <p>
        Nulla facilisi. Vestibulum ante ipsum primis in faucibus orci luctus et
        ultrices posuere cubilia curae.
      </p>
    </div>
  </body>
</html>
Enter fullscreen mode Exit fullscreen mode

Navigate to your "index.js" file and import the following modules:

import { dirname } from "path";
import { fileURLToPath } from "url";
import jsreportClient from "@jsreport/nodejs-client";
import fs from "fs/promises";
import path from "path";
Enter fullscreen mode Exit fullscreen mode

Next, copy the code below to handle the report generation functionality

// Initialize the client with the server URL: This will link the express server to the jsreport server
const client = jsreportClient("http://localhost:5488/");

// programatically derives the file path
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);

// Function to read the HTML template file
async function readHtmlTemplateFile(filename) {
  try {
    const filePath = path.join(__dirname, "/Public/index.html"); // Specifies the path to the html file
    const htmlContent = await fs.readFile(filePath, "utf8");
    return htmlContent;
  } catch (err) {
    throw new Error(`Error reading HTML template file: ${err.message}`);
  }
}

// Handle GET request for /report route
app.get("/report", async (req, res, next) => {
  try {
    const htmlContent = await readHtmlTemplateFile("report-template.html");

    const response = await client.render({
      template: {
        content: htmlContent, // Pass the HTML content read from the file
        recipe: "html", // This specifies the recipe as 'html'
        engine: "none", // No templating engine used ('none' for static HTML)
      },
    });

    // Set headers to indicate file download
    res.setHeader("Content-Disposition", 'attachment; filename="report.html"');
    res.setHeader("Content-Type", "text/html");
    response.pipe(res); // Stream HTML directly to the client for download

    // Pipe the response to the client
    response.pipe(res);
  } catch (err) {
    next(err); // Pass any errors to Express error handling middleware
  }
});
Enter fullscreen mode Exit fullscreen mode

The final javascript code in the "index.js" file should look like this:

import express from "express";
import { dirname } from "path";
import { fileURLToPath } from "url";
import jsreportClient from "@jsreport/nodejs-client";
import fs from "fs/promises";
import path from "path";

const app = express();
const port = 3000;

// Home
app.get("/", (req, res) => {
  res.send("Hello, World!");
});

// Initialize the client with the server URL: This will link the express server to the jsreport server
const client = jsreportClient("http://localhost:5488/");

// programatically derives the file path
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);

// Function to read the HTML template file
async function readHtmlTemplateFile(filename) {
  try {
    const filePath = path.join(__dirname, "/Public/index.html"); // Specifies the path to the html file
    const htmlContent = await fs.readFile(filePath, "utf8");
    return htmlContent;
  } catch (err) {
    throw new Error(`Error reading HTML template file: ${err.message}`);
  }
}

// Handle GET request for /report route
app.get("/report", async (req, res, next) => {
  try {
    const htmlContent = await readHtmlTemplateFile("report-template.html");

    const response = await client.render({
      template: {
        content: htmlContent, // Pass the HTML content read from the file
        recipe: "html", // This specifies the recipe as 'html'
        engine: "none", // No templating engine used ('none' for static HTML)
      },
    });

    // Set headers to indicate file download
    res.setHeader("Content-Disposition", 'attachment; filename="report.html"');
    res.setHeader("Content-Type", "text/html");
    response.pipe(res); // Stream HTML directly to the client for download

    // Pipe the response to the client
    response.pipe(res);
  } catch (err) {
    next(err); // Pass any errors to Express error handling middleware
  }
});

app.listen(port, () => {
  console.log(`Example app listening on port ${port}`);
});
Enter fullscreen mode Exit fullscreen mode

Next is to restart your express server:

node index.js

Once it has been restarted without any issues, head over to your browser and naviagte to http://localhost:3000/report

This would download a simple HTML report for you, that you can preview immediately.

That's it guys! There you go! A lazy programmer's approach to generating reports using the jsreport service. πŸ˜…

I'll see you soon with another article. πŸ‘‹

πŸ’– πŸ’ͺ πŸ™… 🚩
xavier_script
Onwuka David

Posted on July 20, 2024

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related