Enhancing CX: Building a DataMotion-Powered Message Center Widget for React (Part 1)
Published: 2024-03-01 15:18:31

## Introduction 
For any business, efficient and secure communication isn't just beneficial — it's essential. In this guide, we're focusing on creating a widget that centralizes your message management, offering a clear view of your inbox within your dashboard. While today we're honing in on efficiently accessing messages, this foundation sets the stage for a more comprehensive message center. Future expansions could leverage [DataMotion's APIs](https://datamotion.com/portal/project/DataMotion/dashboard) to include sending messages, managing forms, initiating chats, and beyond — paving the way for a fully integrated communication hub.

This tutorial stands out for its versatility and adaptability across various frontend frameworks. Whether you're a fan of Bootstrap, Tailwind, Materialize, or any other, you'll find the concepts and code examples here not just useful but practical and easy to implement. Our goal? To enhance your user interface by centralizing message management, cutting down on the need to juggle between portals for updates, and making the most of what DataMotion's API offers. Let's dive in to make your portal — or any application — more efficient and communicatively robust, one widget at a time.

![SMC Widget Complete](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6ijcrwls3jnp8wy9l59d.png)

---

## Prerequisites
To get the most out of this guide, have the following ready:

- **React and Node.js Knowledge:** Ensure you have a basic understanding of React and Node.js — having a handle on the fundamentals will help you follow along more easily.

- **A React Project:** You'll need an existing React project or dashboard to work with. I'll be using the [CoreUI Free React Admin Template](https://coreui.io/product/free-react-admin-template/) for this tutorial.

- **DataMotion Account:** Make sure you have a [DataMotion](https://datamotion.com/portal/project/DataMotion/dashboard) account to access the APIs. We'll be focusing on the [Secure Message Center API](https://datamotion.com/secure-message-center/) to enhance our project with secure messaging capabilities.

## Setting up the Project
Setting up your project environment is the first step. Skip this part if you're integrating into an existing dashboard.

#### Cloning the Dashboard Template:
If starting new, clone the [CoreUI template](https://github.com/coreui/coreui-free-react-admin-template):

```
# Navigate to your desired project directory
cd [Your_Project_Directory]

# Clone the CoreUI Free React Admin Template from GitHub
git clone https://github.com/coreui/coreui-free-react-admin-template.git

# Change your current directory to the newly cloned project
cd coreui-free-react-admin-template

# Install project dependencies using npm
npm install

# Start the project
npm start
```

#### Environment Setup:
First up, let's prepare our environment. Open the project's terminal to create a dedicated directory for our server, install the necessary packages, and set up our `.env` file for secure API communication.

```
# Create a 'server' directory for our project
mkdir server

# Navigate to the 'server' directory
cd server

# Initialize a new npm project without the interactive prompt
npm init -y

# Install necessary dependencies:
# - Axios for making HTTP requests
# - Dotenv for managing environment variables
# - Express for setting up our server
# - Cors for enabling Cross-Origin Resource Sharing (CORS)
npm install axios dotenv express cors

# Create a '.env' file to securely store your DataMotion API credentials
touch .env
```

Now, add your DataMotion credentials to the newly created `.env` file. This is crucial for authenticating our application with DataMotion's Secure Message Center API:

```
CLIENT_ID=your_datamotion_client_id
CLIENT_SECRET=your_datamotion_client_secret
```

## Building the Message Center Widget
Let's dive into the heart of our project: building the message center widget. We'll start by setting up our server and establishing a connection with DataMotion.

```
# Create a 'server.js' file where our server setup will live
touch server.js
```

#### Server Setup:
Below, we're setting up a basic server using Node.js and Express. This server will manage our requests to DataMotion's API.

```
// Import necessary modules: Express for the server, Axios for HTTP requests, CORS, and Dotenv to use environment variables
const express = require('express')
const axios = require('axios')
const cors = require('cors')
require('dotenv').config() // Load our environment variables from the '.env' file

const app = express() // Create an instance of the express application
const PORT = process.env.PORT || 5000 // Define the port our server will run on

app.use(cors())

// Add your API routes and handlers here

// Start the server and listen on the defined PORT
app.listen(PORT, () => {
  console.log(`Server running on port ${PORT}`)
})
```

#### Testing the Server:
To ensure that your server is up and running, simply execute the following command:

```
node server.js
```

If your server is set up correctly, you should see a message in your terminal indicating that the server is running on the specified port: `Server running on port 5000`.

> **Note:** Throughout the tutorial, whenever you make changes to the server code, remember to restart it using the `node server.js` command to apply those changes.

#### Authentication with DataMotion:
To securely access DataMotion's API, we need to authenticate our application. Here's how we obtain an access token using client credentials:

```
// Define a route to get an access token from DataMotion
app.get('/token', async (req, res) => {
  try {
    // Make a POST request to DataMotion's token endpoint with our client credentials
    const response = await axios.post('https://api.datamotion.com/SMC/Messaging/v3/token', {
      grant_type: 'client_credentials',
      client_id: process.env.CLIENT_ID, // Use the client ID from our .env file
      client_secret: process.env.CLIENT_SECRET, // Use the client secret from our .env file
    })
    res.json(response.data)
  } catch (error) {
    res.status(500).json({ message: 'Error fetching token', error: error.response.data })
  }
})
```

#### Fetching Messages from Different Folders
To tailor our secure message widget to show messages from various folders, we use the `folderId` parameter in the API request. This parameter helps us specify which folder we want to access. For example, setting `folderId=1` lets us retrieve messages from the inbox. Here's how different folders are identified within DataMotion's system, using their respective folderId values:

- Inbox: `folderId = 1`
- Trash: `folderId = 2`
- Track Sent: `folderId = 3`
- Drafts: `folderId = 4`
- Outbox Trash: `folderId = 5`
- Archive: `folderId = 6`
- Deleted Inbox Trash: `folderId = 7`
- Deleted Outbox Trash: `folderId = 8`

Understanding these folder IDs allows you to customize which messages to display, enhancing the widget's functionality.

Here's how we fetch messages from the inbox as an example:

```
// Define a route to get messages from the inbox
app.get('/messages', async (req, res) => {
  try {
     // First, obtain an access token from DataMotion
    const tokenResponse = await axios.post('https://api.datamotion.com/SMC/Messaging/v3/token', {
      grant_type: 'client_credentials',
      client_id: process.env.CLIENT_ID,  // Your DataMotion client ID
      client_secret: process.env.CLIENT_SECRET,  // Your DataMotion client secret
    });

   // Then, use the token to fetch messages from the inbox
    const messagesResponse = await axios.get('https://api.datamotion.com/SMC/Messaging/v3/content/messages/?folderId=1&pageSize=10&pageNumber=1&sortDirection=DESC&metadata=true', {
      headers: {
        Authorization: `Bearer ${tokenResponse.data.access_token}`  // Authorization header with the access token
      }
    });

      res.json(messagesResponse.data)
  } catch (error) {
    res.status(500).json({ message: 'Error fetching messages', error: error.response.data })
  }
})
```

This approach ensures you can dynamically display messages from any folder, making your email widget both versatile and user-friendly.

## Building and Integrating the Message Center Widget into the Dashboard
Our next step is to bring Secure Message Center API's power directly to our dashboard. We'll achieve this by creating a dedicated React component, `MessageCenterWidget`, which will serve as the core interface for displaying messages.

#### Creating the Component File
Before we start coding, we need to create the file where our `MessageCenterWidget` component will reside:

```
# Navigate to the src/components directory of your project
cd src/components

# Create the MessageCenterWidget.js file
touch MessageCenterWidget.js
```

With the file created, open `MessageCenterWidget.js` in your code editor to begin implementing the component.

#### Setting Up and Importing Dependencies
At the top of the `MessageCenterWidget.js` file, import the necessary dependencies for our component. This includes React for building the component, Axios for HTTP requests, and specific CoreUI components for styling our message display.

```
// Importing React, Axios, and selected CoreUI components
import React, { useEffect, useState } from 'react';
import axios from 'axios';
import {
  CCard,
  CCardBody,
  CCardHeader,
  CTable,
  CTableBody,
  CTableDataCell,
  CTableHead,
  CTableHeaderCell,
  CTableRow,
} from '@coreui/react';
```

#### Initializing State Variables
Define the initial state within the `MessageCenterWidget` component to manage the fetched messages and the loading status.

```
// MessageCenterWidget component definition
const MessageCenterWidget = () => {
  const [messages, setMessages] = useState([]) // Array to hold our fetched messages
  const [isLoading, setIsLoading] = useState(true) // Boolean to track loading status

  // Additional logic will follow
}
```

#### Fetching and Displaying Emails
Utilize the `useEffect` hook for fetching messages as soon as the component mounts, ensuring our dashboard is immediately populated with data.

```
  // Additional logic will follow
  useEffect(() => {
    const fetchMessages = async () => {
      try {
        // Step 1: Securely obtain an authentication token
        const tokenResponse = await axios.get('http://localhost:5000/token')
        // Step 2: Fetch messages using the obtained token
        const messagesResponse = await axios.get('http://localhost:5000/messages', {
          headers: {
            Authorization: `Bearer ${tokenResponse.data.access_token}`, // Use the token in the request header
          },
        })
        // Sort the fetched messages by creation time before updating state
        const sortedMessages = messagesResponse.data.items.sort(
          (a, b) => new Date(b.createTime) - new Date(a.createTime),
        )
        setMessages(sortedMessages)
      } catch (error) {
        console.error('Error fetching messages:', error)
      } finally {
        setIsLoading(false) // Ensure to update the isLoading state
      }
    }

    fetchMessages()
  }, [])
```

#### Sorting Emails and Formatting Dates
Implement a helper function to format message dates for a better user experience, and prepare the component for rendering.

```
  // Function to format the date strings of messages
  const formatDate = (dateString) => {
    const date = new Date(dateString)
    const today = new Date()

    // Display format differs if the message is from today or an earlier date
    return date.toDateString() === today.toDateString()
      ? date.toLocaleTimeString()
      : date.toLocaleDateString()
  }

  // Render loading indicator or the message table based on the isLoading state
  if (isLoading) {
    return <div>Loading messages...</div>
  }
```

Ensure to export your `MessageCenterWidget` at the end of the file for it to be used elsewhere in your project.

```
// Make the MessageCenterWidget available for import
export default MessageCenterWidget
```

#### Rendering the Secure Message Center 
Now that we've established the logic for fetching and displaying messages, let's focus on presenting this information through a user-friendly and visually appealing table. We'll enhance our table's appearance and functionality with some custom CSS styling.

#### Adding CSS for Table Styling
First, we add CSS to ensure our table looks organized and maintains a consistent layout. Place this CSS in an appropriate stylesheet or within your component using styled-components or a similar approach, depending on your project setup.

```
/* CSS styles for the message center table */
.message-center-table-container {
  max-height: 600px;

  table {
    width: 100%;
    table-layout: fixed;
  }

  thead th,
  tbody td {
    text-align: left;
    width: 33.33%;
  }
}

.title-style {
  font-size: 1rem;
  font-weight: 400;
  margin-top: auto;
  margin-bottom: auto;
}
```

#### JSX Structure for the Secure Message Center 
Utilizing CoreUI's table components, we can neatly organize and display the sender, subject, and date of each message. Here's the JSX that incorporates our CSS styling:

```
  return (
    <CCard className="mb-4">
      <CCardHeader>Secure Message Center</CCardHeader>
      <CCardBody>
        <div className="message-table">
          <CTable align="middle" className="mb-4 border" hover responsive>
            <CTableHead>
              <CTableRow>
                <CTableHeaderCell scope="col" className="">
                  Sender
                </CTableHeaderCell>
                <CTableHeaderCell scope="col" className="">
                  Subject
                </CTableHeaderCell>
                <CTableHeaderCell scope="col" className="">
                  Date
                </CTableHeaderCell>
              </CTableRow>
            </CTableHead>
            <CTableBody className="table-body">
              {emails.length > 0 ? (
                emails.map((email, index) => (
                  <CTableRow key={index}>
                    <CTableDataCell>{email.senderAddress}</CTableDataCell>
                    <CTableDataCell>{email.subject}</CTableDataCell>
                    <CTableDataCell>{formatDate(email.createTime)}</CTableDataCell>
                  </CTableRow>
                ))
              ) : (
                <CTableRow>
                  <CTableDataCell colSpan={3}>No emails found</CTableDataCell>
                </CTableRow>
              )}
            </CTableBody>
          </CTable>
        </div>
      </CCardBody>
    </CCard>
  );
};
```
This structure leverages our CSS to create a clean, organized display for the messages, significantly enhancing the user experience of the dashboard.

## Integrating the Widget into the Dashboard
Now that our `MessageCenterWidget` is ready and prepped with its functionality and styling, the final step is to weave it into the fabric of our dashboard. This phase is crucial for bringing the secure messaging capabilities directly to the users’ fingertips, enhancing the dashboard’s overall utility and user experience.

#### Placing the MessageCenterWidget in the Dashboard
Integration is straightforward. Assuming you have a `Dashboard.js` file or a similar setup for your main dashboard component, you’ll incorporate the `MessageCenterWidget` like so:

```
// Ensure the MessageCenterWidget is imported at the top of your Dashboard component file
import MessageCenterWidget from '../../components/MessageCenterWidget'

const Dashboard = () => {
  // Include other dashboard components and logic as needed

  return (
    <>
      <WidgetsDropdown className="mb-4" />
      {/* Position the MessageCenterWidget where it fits best in your dashboard layout */}
      <MessageCenterWidget className="mb-4" />
      {/* Continue with the rest of your dashboard components */}
      <CCard className="mb-4">
        {/* Remaining dashboard components... */}
      </CCard>
      {/* Other components... */}
    </>
  );
};

export default Dashboard
```

This step integrates the MessageCenterWidget into your dashboard. Depending on your design, you might adjust its placement, ensuring it complements the overall layout and flow of the dashboard. The widget’s self-contained nature makes it adaptable to various positions and configurations, affirming the modular and flexible design of React components.

![SMC Widget - Inbox Messages](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bsacefnl4zu88risoqgt.png)

---

## Expanding the Widget's Functionality
After initially focusing on showcasing the inbox, it's time to broaden the capabilities of our widget. We'll introduce functionality that allows users to switch between viewing inbox and sent messages, similar to standard email clients.

#### Updating the Server to Fetch Sent Messages
To facilitate the display of both received and sent messages, let's extend our server's capabilities with an additional endpoint. This step involves navigating back to the `server` directory to modify the `server.js` file.

```
// New endpoint to fetch sent messages
app.get('/sent-messages', async (req, res) => {
  try {
    const tokenResponse = await axios.post('https://api.datamotion.com/SMC/Messaging/v3/token', {
      grant_type: 'client_credentials',
      client_id: process.env.CLIENT_ID,
      client_secret: process.env.CLIENT_SECRET,
    })

    const sentMessagesResponse = await axios.get(
      'https://api.datamotion.com/SMC/Messaging/v3/content/messages/?folderId=3&pageSize=10&pageNumber=1&sortDirection=DESC&metadata=true',
      {
        headers: {
          Authorization: `Bearer ${tokenResponse.data.access_token}`,
        },
      },
    )
    res.json(sentMessagesResponse.data)
  } catch (error) {
    res.status(500).json({ message: 'Error fetching sent messages', error: error.response.data })
  }
})
```
> **Note:** Changing `folderId` to 3 targets sent messages, as mentioned earlier.

#### Integrating Sidebar and Updating MessageCenterWidget.js
With our backend ready to serve both inbox and sent messages, it's time to update the frontend in `MessageCenterWidget.js`. This involves implementing a sidebar for mailbox selection and adjusting our component to utilize the new `/sent-messages` endpoint.

Update `MessageCenterWidget.js` to manage the view selection state:

```
const MessageCenterWidget = () => {
  const [messages, setMessages] = useState([]) // Holds our fetched messages (unchanged)
  const [isLoading, setIsLoading] = useState(true) // Tracks loading status (unchanged)
  
  // New state to manage the current mailbox view ('inbox' or 'sent')
  const [currentView, setCurrentView] = useState('inbox')
}

```

> **Note:** The addition of currentView and setCurrentView allows us to dynamically fetch and display messages based on the user's selection between different mailbox views, such as the inbox or sent messages.

Next, we adapt the `useEffect` hook to react to mailbox changes, fetching messages accordingly:

```
useEffect(() => {
  const fetchEmails = async () => {
    setIsLoading(true)
    let endpoint = ''

    if (currentView === 'inbox') {
      endpoint = '/messages'
    } else if (currentView === 'sent') {
      endpoint = '/sent-messages'
    } else if (currentView === 'drafts') {
      endpoint = '/drafts'
    } else if (currentView === 'trash') {
      endpoint = '/trash'
    }

    try {
      const tokenResponse = await axios.get('http://localhost:5000/token')
      const messagesResponse = await axios.get(`http://localhost:5000${endpoint}`, {
        headers: {
          Authorization: `Bearer ${tokenResponse.data.access_token}`,
        },
      })
      const sortedEmails = messagesResponse.data.items.sort(
        (a, b) => new Date(b.createTime) - new Date(a.createTime),
      )
      setMessages(sortedEmails)
    } catch (error) {
      console.error(`Error fetching ${currentView} emails:`, error)
    } finally {
      setIsLoading(false)
    }
  }

  fetchEmails()
}, [currentView])
```

Within the JSX, we introduce the sidebar for mailbox switching, enhancing the component's interactivity:

```
return (
  <CCard className="mb-4 email-table">
    <CCardHeader>Secure Message Center</CCardHeader>
    <div className="d-flex">
      <div className="email-sidebar">
        <ul>
          <li
            className={currentView === 'inbox' ? 'active' : ''}
            onClick={() => setCurrentView('inbox')}
          >
            Inbox
          </li>
          <li
            className={currentView === 'sent' ? 'active' : ''}
            onClick={() => setCurrentView('sent')}
          >
            Sent
          </li>
          {/* Add more folders if needed */}
        </ul>
      </div>
      <CCardBody>
        {/* Table rendering logic */}
      </CCardBody>
    </div>
  </CCard>
);
```

This update significantly enriches the widget by offering users a more dynamic tool that mirrors the functionality of full-featured email clients. By facilitating the navigation between inbox and sent messages, the widget evolves into a more versatile component of the dashboard.

#### Styling the Sidebar
To ensure our sidebar is not only functional but also aesthetically pleasing, let's add some CSS:

```
.email-sidebar {
  width: 150px;
  background-color: #f8f9fa;
  padding: .5rem;
}

.email-sidebar ul {
  list-style-type: none;
  padding: 0;
}

.email-sidebar ul li {
  padding: .25rem;
  cursor: pointer;
  font-weight: 500;
  color: #495057;
}

.email-sidebar ul li.active {
  background-color: #e9ecef;
}

.email-sidebar ul li:hover {
  background-color: #dee2e6;
}

.placeholder {
  background-color: #f0f0f0;
  height: 1em; 
  width: 100%;
  border-radius: 4px;
}
```

Apply these styles to make the sidebar both functional and stylish.

![Expanded Widget with Sidebar](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nqs075cms6dpucepe6ht.png)

## Conclusion of the Expanded Widget
Integrating DataMotion's Secure Message Center API into our dashboard has improved how we manage messages, showcasing the power and flexibility of DataMotion's tools. This tutorial highlighted the straightforward process of incorporating these APIs with the CoreUI framework, proving how they can enhance any user interface with secure and efficient communication.

This project is a clear example of DataMotion's ability to provide secure communication solutions that are both powerful and user-friendly. We've started to explore the potential of DataMotion's Secure Message Center APIs, demonstrating that secure communication can be seamlessly integrated into any digital environment, offering both customization and compliance.

DataMotion's APIs are designed to support secure, engaging, and efficient digital experiences, whether you're improving an existing system or creating something new. 

As we wrap up, consider this guide a starting point for discovering all that DataMotion has to offer. Check back for a part two, where we will build upon this groundwork to further expand your expertise and success. 

---

**Quick Links:**
- [Github Repository](https://github.com/janellephalon/smc-api-dashboard-widget/tree/main)
- [DataMotion](www.datamotion.com) & [DataMotion APIs](https://datamotion.com/portal/project/DataMotion/dashboard)
- [Core UI](https://coreui.io/)
- [React](https://react.dev/)