James Ellis

James Ellis

1574780331

Send chat transcripts with Chatkit and Sendgrid

In this tutorial, we’ll take a look at how chat transcripts can be retrieved and sent to an email address using Sendgrid’s API. Here’s a demo of what we’ll be building:

A common feature on most customer support chat systems is the ability to send a transcript of a chat session after it ends. This provides a reference for customers in case they need to remember something that was discussed during a particular chat session.

Prerequisites

To follow along with this tutorial, you need to have Node.js (version 8 or later), and npm installed on your machine. Prior experience with React and Chatkit is also required for you to gain a full understanding of how the code that will be written in the tutorial works.

Sign up for Chatkit

Open this link to create a new Chatkit account or login to your existing account. Once you’re logged in, create a new Chatkit instance for this tutorial, then locate the Credentials tab on your instance’s dashboard and take note of the Instance Locator and Secret Key.

Also make sure the Test Token Provider for the instance is active as shown below. Once enabled, the URL from which the test token will be generated will be displayed on the page.

Head over to the Console tab, and create a new user for your application. This will be the user account for the support staff who will interact with customers. The user identifier for this user should be support as shown below:

Sign up for SendGrid

Create a free account at Sendgrid.com. Once you’re logged in, select Settings > API Keys on the sidebar and then create a new API key. Give your API key a name, and select Full Access under API Key Permissions. Once your key is created, keep it in view until after we’ve added it to an .env file in the next section.

Set up the server

Launch a new terminal instance and create a new directory for your project as shown below:

    mkdir chat-transcript-tutorial

Next, cd into the new directory and initialize your project with a package.json file using the npm init -y command. Following that, run the command below to install all the dependencies that we’ll need to build our Node server.

    npm install express dotenv body-parser @pusher/chatkit-server cors date-fns @sendgrid/mail --save

Next, create a .env file in the root of your project directory and paste in the credentials you retrieved from your Chatkit and Sendgrid dashboards respectively:

    // .env

    PORT=5200
    CHATKIT_INSTANCE_LOCATOR=<your chatkit instance locator>
    CHATKIT_SECRET_KEY=<your chatkit secret key>
    SENDGRID_API_KEY=<your sendgrid api key>

Create another file, server.js in the root of your project directory, and add the following code into it to set up the Node server:

    require('dotenv').config({ path: '.env' });

    const express = require('express');
    const bodyParser = require('body-parser');
    const cors = require('cors');
    const Chatkit = require('@pusher/chatkit-server');
    const dateFns = require('date-fns');

    const sgMail = require('@sendgrid/mail')

    sgMail.setApiKey(process.env.SENDGRID_API_KEY)

    const app = express();

    const chatkit = new Chatkit.default({
      instanceLocator: process.env.CHATKIT_INSTANCE_LOCATOR,
      key: process.env.CHATKIT_SECRET_KEY,
    });

    app.use(cors());
    app.use(bodyParser.json());
    app.use(bodyParser.urlencoded({ extended: true }));

    app.post('/users', (req, res) => {
      const { username } = req.body;

      chatkit
        .createUser({
          id: username,
          name: username,
        })
        .then(() => {
          res.sendStatus(201);
        })
        .catch(err => {
          if (err.error === 'services/chatkit/user_already_exists') {
            console.log(`User already exists: ${username}`);
            res.sendStatus(200);
          } else {
            res.status(err.status).json(err);
          }
        });
    });

    app.post('/transcript', (req, res) => {
      const { roomId, email, name } = req.body;
      chatkit.fetchMultipartMessages({
        roomId,
        limit: 100,
      })
        .then(messages => {
          const t = constructTranscript(messages);

          const msg = {
            to: email,
            from: 'noreply@fictionalservice.com',
            subject: 'Chat transcript',
            html: `
              <p>Dear ${name},</p>

              <p>Thank you for taking the time to chat with us today. Below is a copy of your chat transcript for future reference.</p>

              <p><strong>Chat ${dateFns.format(new Date(), 'DD/MM/YYYY HH:mm')}</strong></p>
              <ul>
                ${t.join('')}
              </ul>

              <p>Thank you,</p>
              <p>Customer Care</p>
            `,
          };

          return sgMail.send(msg)
        })
        .then(() => {
          res.send("Success!");
        })
        .catch((err) => {
          console.error(err);
          res.status(500).send("An error occured");
        });
    });

    function constructTranscript(messages) {
        return messages.reverse().map(message => {
          return `
            <li className="message">
              <div>
                <span>[${dateFns.format(message.created_at, 'DD/MM/YYYY HH:mm')}]</span>
                <strong className="user-id">${message.user_id}:</strong>
                <span className="message-text">${message.parts[0].content}</span>
              </div>
            </li>
          `
        });
    }

    app.set('port', process.env.PORT || 5200);
    const server = app.listen(app.get('port'), () => {
      console.log(`Express running → PORT ${server.address().port}`);
    });

If you’ve worked with Chatkit before, this should all be familiar to you. Otherwise, here’s a brief explanation:

  • First instantiate our chatkit instance using the Instance Locator and Secret Key noted in the previous step.
  • In the /users route, we take a username and create a Chatkit user through our chatkit instance.
  • The /transcript route is where messages from a room are fetched, processed into an HTML template, and sent to an email address via Sendgrid. We’ll take a closer look at what this code does in a later section.

You can go ahead and start the server on port 5200 by running node server.js in the terminal.

Set up the application frontend

Install create-react-app globally, then use it to bootstrap a new React application:

    npm install -g create-react-app
    create-react-app frontend

Once the app has been created, cd into the new directory and install the following additional dependencies that we’ll be needing in the course of building the chat app, then launch the development server on http://localhost:3000:

    npm install @pusher/chatkit-client react-toastify axios random-words --save
    npm start

Add the styles for the application

Open up frontend/src/App.css and change its contents to look like this:

    // frontend/src/App.css

    html {
      box-sizing: border-box;
    }

    *, *::before, *::after {
      box-sizing: inherit;
      margin: 0;
      padding: 0;
    }

    .login-form {
      position: absolute;
      top: 50%;
      left: 50%;
      transform: translate(-50%, -50%);
      border: 1px solid #ddd;
      padding: 20px;
      width: 100%;
      max-width: 500px;
    }

    .login-form h2 {
      margin-bottom: 20px;
    }

    button[type="submit"] {
      width: 100%;
      padding: 10px;
      font-size: 18px;
      color: #fff;
      background-color: #000;
      cursor: pointer;
      border: 1px solid transparent;
    }

    button[type="submit"]:hover {
      color: #000;
      background-color: #fff;
      border: 1px solid #dcc;
    }

    input {
      width: 100%;
      margin-bottom: 20px;
      padding: 10px;
      border: 1px solid #ccc;
    }

    label {
      margin-bottom: 10px;
      display: inline-block;
    }

    /* Chat Widget
       ========================================================================== */

    .chat-widget {
      position: absolute;
      bottom: 20px;
      right: 60px;
      border: 1px solid #ccc;
      height: 500px;
      width: 350px;
      display: flex;
      flex-direction: column;
    }

    .chat-header {
      border-bottom: 1px solid #ccc;
      padding: 10px 15px;
      display: flex;
      justify-content: space-between;
      align-items: center;
    }

    .chat-header h2 {
      font-size: 20px;
    }

    .end-chat {
      background: transparent;
      border: none;
    }

    .chat-messages {
      padding: 15px;
      flex-grow: 1;
      list-style: none;
    }

    .chat-messages li {
      margin-bottom: 10px;
    }

    .message-input {
      margin-bottom: 0;
      border: none;
      border-top: 1px solid #ccc;
    }

    .notice {
      display: none;
    }

    .dialog-container {
      position: absolute;
      top: 0;
      right: 0;
      bottom: 0;
      left: 0;
      background-color: rgba(0, 0, 0, 0.8);
      display: flex;
      justify-content:center;
      align-items: center;
    }

    .dialog {
      width: 500px;
      background-color: white;
      display: flex;
      align-items:  center;
    }

    .dialog-form {
      width: 100%;
      margin-bottom: 0;
      padding: 20px;
    }

    .dialog-form > * {
      display: block;
    }

    .submit-btn {
      color: #5C8436;
      background-color: #181919;
      width: 100%;
    }

    .submit-btn:hover {
      color: #5C8436;
      background-color: #222;
    }

Create a basic chat application

This next step involves creating a simple interface with which a potential customer will interact with a support agent. Open up frontend/src/App.js and change it to look like this:

    // frontend/src/App.js

    import React from 'react';
    import { handleInput, joinChat, sendMessage, endChat, sendTranscript } from './methods.js';
    import { ToastContainer } from 'react-toastify';

    import 'react-toastify/dist/ReactToastify.min.css';
    import './App.css';

    class App extends React.Component {
      constructor() {
        super();
        this.state = {
          showTranscriptDialog: false,
          transcriptEmail: "",
          username: "",
          currentRoom: null,
          currentUser: null,
          messages: [],
          newMessage: "",
        }

        this.handleInput = handleInput.bind(this);
        this.joinChat = joinChat.bind(this);
        this.sendMessage = sendMessage.bind(this);
        this.endChat = endChat.bind(this);
        this.sendTranscript = sendTranscript.bind(this);
      }

      render() {
        const { currentUser, messages, newMessage, showTranscriptDialog } = this.state;

        const messageList = messages.map(message => {
          const arr = message.parts.map(p => {
            return (
              <span className="message-text">{p.payload.content}</span>
            );
          });

          return (
            <li className="message" key={message.id}>
              <div>
                <span className="user-id"><strong>{message.sender.name}: </strong></span>
                {arr}
              </div>
            </li>
          )
        });

        return (
          <div className="App">
            {!currentUser ? (
              <div className="login-form">
                <h2>Chat with a Support Agent</h2>
                <form onSubmit={this.joinChat}>
                    <label htmlFor="username">Enter your username</label>
                    <input onChange={this.handleInput} type="text" id="username" name="username"
                      placeholder="Username" />
                      <button type="submit">Start chatting!</button>
                    </form>
                  </div>
            ) : (
              <div className="chat-widget">
                <header className="chat-header">
                  <h2>Support</h2>
                  <button onClick={this.endChat} className="end-chat">
                    End Chat
                  </button>
                </header>
                <ul className="chat-messages">
                  {messageList}
                </ul>

                <form onSubmit={this.sendMessage} className="message-form">
                  <input
                    className="message-input"
                    autoFocus
                    name="newMessage"
                    placeholder="Compose your message and hit ENTER to send"
                    onChange={this.handleInput}
                    value={newMessage}
                  />
                </form>
              </div>
              )}

              <ToastContainer />

              {showTranscriptDialog ? (
                <div className="dialog-container">
                  <div className="dialog">
                    <form className="dialog-form" onSubmit={this.sendTranscript}>
                      <label htmlFor="email">Send a transcript of the chat to the following email address:</label>
                      <input onChange={this.handleInput} type="email" id="email" name="transcriptEmail"
                        placeholder="name@example.com" />
                      <button type="submit" className="submit-btn">
                        Send transcript
                      </button>
                      </form>
                    </div>
                  </div>
              ) : null}
          </div>
        );
      }
    }

    export default App;

Create a new methods.js file within the src directory and add the following code to it:

    import axios from 'axios';
    import { ChatManager, TokenProvider } from '@pusher/chatkit-client'
    import { toast } from 'react-toastify';
    import randomWords from 'random-words';

    function handleInput(event) {
      const { value, name } = event.target;

      this.setState({
        [name]: value
      });
    }

    function addSupportStaffToRoom() {
      const { currentRoom, currentUser } = this.state;

      return currentUser.addUserToRoom({
        userId: "support",
        roomId: currentRoom.id
      });
    };

    function createRoom() {
      const { currentUser } = this.state;

      currentUser
        .createRoom({
          name: randomWords({ exactly: 2, join: ' ' }),
          private: true
        })
        .then(room => connectToRoom.call(this, room.id))
        .then(() => addSupportStaffToRoom.call(this))
        .catch(console.error);
    };

    function connectToRoom(id) {
      const { currentUser } = this.state;

      return currentUser
        .subscribeToRoomMultipart({
          roomId: `${id}`,
          messageLimit: 100,
          hooks: {
            onMessage: message => {
              this.setState({
                messages: [...this.state.messages, message]
              });
            },
          }
        })
        .then(currentRoom => {
          this.setState({
            currentRoom
          });
        });
    }

    function joinChat(event) {
      event.preventDefault();

      const { username } = this.state;

      if (username.trim() === "") {
        alert("A valid username is required");
      } else {
        axios
          .post("http://localhost:5200/users", { username })
          .then(() => {
            const tokenProvider = new TokenProvider({
              url: "<your token provider endpoint>"
            });

            const chatManager = new ChatManager({
              instanceLocator: "<your chatkit instance locator>",
              userId: username,
              tokenProvider
            });

            return chatManager.connect().then(currentUser => {
              console.log(currentUser);
              this.setState(
                {
                  currentUser,
                },
                () => createRoom.call(this)
              );
            });
          })
          .catch(console.error);
      }
    }

    function sendMessage(event) {
      event.preventDefault();
      const { newMessage, currentUser, currentRoom } = this.state;

      if (newMessage.trim() === "") return;

      currentUser.sendSimpleMessage({
        roomId: `${currentRoom.id}`,
        text: newMessage
      });

      this.setState({
        newMessage: "",
      });
    }

    function endChat(event) {
      event.preventDefault();

      this.setState({
        showTranscriptDialog: true
      });
    }

    function sendTranscript(event) {
      event.preventDefault();

      const { currentRoom, currentUser, transcriptEmail } = this.state;

      axios.post("http://localhost:5200/transcript", {
        roomId: currentRoom.id,
        email: transcriptEmail,
        name: currentUser.name,
      })
        .then(res => {
          toast.success("Transcript sent successfully!");

          this.setState({
            showTranscriptDialog: false,
            transcriptEmail: "",
          })
        })
        .catch(err => {
          console.error(err);
          toast.error("An problem occured");
        })
        .finally(() => {
          currentUser.disconnect();
          this.setState({
            currentUser: null,
            currentRoom: null,
            messages: [],
            newMessage: "",
          })
        });
    }

    export {
      handleInput,
      joinChat,
      sendMessage,
      endChat,
      sendTranscript,
    }

Don’t forget to replace the <your token provider endpoint> and <your chatkit instance locator> placeholders above with the appropriate values from your Chatkit dashboard.

Here’s a quick run down on what the code above does:

  • Once a user connects to the Chatkit instance, a new room is created for the interaction through the createRoom() method.
  • Once the user is connected to the room, the support staff agent is also added to the room instantaneously. In a real world application, you will probably have several support agents, so there will be a (hopefully short) waiting time for the user before they are connected to an available agent.
  • Messages can now be sent back and forth between the current user and the support agent. You can navigate to the Console tab on the instance dashboard to add a message to the room as the Support agent.
  • Once the chat is ended, a new dialog will appear prompting the user to enter an email address where the transcript will be sent.
  • The sendTranscript() function makes a request to the /transcript endpoint on the server, and passes along the email address along with the room’s ID.
  • If you look at the /transcript endpoint on the server, you will see that it simply fetches the messages in the room, and constructs some HTML which is then sent to the provided email address via SendGrid’s API.

Here’s how the above process looks like in practice:

Wrap up

In this tutorial, we covered how to send chat transcripts with Chatkit and Sendgrid. We covered a simple use case but you can take it further by customizing the transcript email template or creating an archive of all your chats which can come in handy if you need to keep a record of past chats on file for all of your agents.

You can checkout other things Chatkit can do by viewing its extensive documentation. Don’t forget to grab the full source code used in this tutorial here.

#reactjs #Sendgrid #javascript #Chatkit

What is GEEK

Buddha Community

Send chat transcripts with Chatkit and Sendgrid
James Ellis

James Ellis

1574780331

Send chat transcripts with Chatkit and Sendgrid

In this tutorial, we’ll take a look at how chat transcripts can be retrieved and sent to an email address using Sendgrid’s API. Here’s a demo of what we’ll be building:

A common feature on most customer support chat systems is the ability to send a transcript of a chat session after it ends. This provides a reference for customers in case they need to remember something that was discussed during a particular chat session.

Prerequisites

To follow along with this tutorial, you need to have Node.js (version 8 or later), and npm installed on your machine. Prior experience with React and Chatkit is also required for you to gain a full understanding of how the code that will be written in the tutorial works.

Sign up for Chatkit

Open this link to create a new Chatkit account or login to your existing account. Once you’re logged in, create a new Chatkit instance for this tutorial, then locate the Credentials tab on your instance’s dashboard and take note of the Instance Locator and Secret Key.

Also make sure the Test Token Provider for the instance is active as shown below. Once enabled, the URL from which the test token will be generated will be displayed on the page.

Head over to the Console tab, and create a new user for your application. This will be the user account for the support staff who will interact with customers. The user identifier for this user should be support as shown below:

Sign up for SendGrid

Create a free account at Sendgrid.com. Once you’re logged in, select Settings > API Keys on the sidebar and then create a new API key. Give your API key a name, and select Full Access under API Key Permissions. Once your key is created, keep it in view until after we’ve added it to an .env file in the next section.

Set up the server

Launch a new terminal instance and create a new directory for your project as shown below:

    mkdir chat-transcript-tutorial

Next, cd into the new directory and initialize your project with a package.json file using the npm init -y command. Following that, run the command below to install all the dependencies that we’ll need to build our Node server.

    npm install express dotenv body-parser @pusher/chatkit-server cors date-fns @sendgrid/mail --save

Next, create a .env file in the root of your project directory and paste in the credentials you retrieved from your Chatkit and Sendgrid dashboards respectively:

    // .env

    PORT=5200
    CHATKIT_INSTANCE_LOCATOR=<your chatkit instance locator>
    CHATKIT_SECRET_KEY=<your chatkit secret key>
    SENDGRID_API_KEY=<your sendgrid api key>

Create another file, server.js in the root of your project directory, and add the following code into it to set up the Node server:

    require('dotenv').config({ path: '.env' });

    const express = require('express');
    const bodyParser = require('body-parser');
    const cors = require('cors');
    const Chatkit = require('@pusher/chatkit-server');
    const dateFns = require('date-fns');

    const sgMail = require('@sendgrid/mail')

    sgMail.setApiKey(process.env.SENDGRID_API_KEY)

    const app = express();

    const chatkit = new Chatkit.default({
      instanceLocator: process.env.CHATKIT_INSTANCE_LOCATOR,
      key: process.env.CHATKIT_SECRET_KEY,
    });

    app.use(cors());
    app.use(bodyParser.json());
    app.use(bodyParser.urlencoded({ extended: true }));

    app.post('/users', (req, res) => {
      const { username } = req.body;

      chatkit
        .createUser({
          id: username,
          name: username,
        })
        .then(() => {
          res.sendStatus(201);
        })
        .catch(err => {
          if (err.error === 'services/chatkit/user_already_exists') {
            console.log(`User already exists: ${username}`);
            res.sendStatus(200);
          } else {
            res.status(err.status).json(err);
          }
        });
    });

    app.post('/transcript', (req, res) => {
      const { roomId, email, name } = req.body;
      chatkit.fetchMultipartMessages({
        roomId,
        limit: 100,
      })
        .then(messages => {
          const t = constructTranscript(messages);

          const msg = {
            to: email,
            from: 'noreply@fictionalservice.com',
            subject: 'Chat transcript',
            html: `
              <p>Dear ${name},</p>

              <p>Thank you for taking the time to chat with us today. Below is a copy of your chat transcript for future reference.</p>

              <p><strong>Chat ${dateFns.format(new Date(), 'DD/MM/YYYY HH:mm')}</strong></p>
              <ul>
                ${t.join('')}
              </ul>

              <p>Thank you,</p>
              <p>Customer Care</p>
            `,
          };

          return sgMail.send(msg)
        })
        .then(() => {
          res.send("Success!");
        })
        .catch((err) => {
          console.error(err);
          res.status(500).send("An error occured");
        });
    });

    function constructTranscript(messages) {
        return messages.reverse().map(message => {
          return `
            <li className="message">
              <div>
                <span>[${dateFns.format(message.created_at, 'DD/MM/YYYY HH:mm')}]</span>
                <strong className="user-id">${message.user_id}:</strong>
                <span className="message-text">${message.parts[0].content}</span>
              </div>
            </li>
          `
        });
    }

    app.set('port', process.env.PORT || 5200);
    const server = app.listen(app.get('port'), () => {
      console.log(`Express running → PORT ${server.address().port}`);
    });

If you’ve worked with Chatkit before, this should all be familiar to you. Otherwise, here’s a brief explanation:

  • First instantiate our chatkit instance using the Instance Locator and Secret Key noted in the previous step.
  • In the /users route, we take a username and create a Chatkit user through our chatkit instance.
  • The /transcript route is where messages from a room are fetched, processed into an HTML template, and sent to an email address via Sendgrid. We’ll take a closer look at what this code does in a later section.

You can go ahead and start the server on port 5200 by running node server.js in the terminal.

Set up the application frontend

Install create-react-app globally, then use it to bootstrap a new React application:

    npm install -g create-react-app
    create-react-app frontend

Once the app has been created, cd into the new directory and install the following additional dependencies that we’ll be needing in the course of building the chat app, then launch the development server on http://localhost:3000:

    npm install @pusher/chatkit-client react-toastify axios random-words --save
    npm start

Add the styles for the application

Open up frontend/src/App.css and change its contents to look like this:

    // frontend/src/App.css

    html {
      box-sizing: border-box;
    }

    *, *::before, *::after {
      box-sizing: inherit;
      margin: 0;
      padding: 0;
    }

    .login-form {
      position: absolute;
      top: 50%;
      left: 50%;
      transform: translate(-50%, -50%);
      border: 1px solid #ddd;
      padding: 20px;
      width: 100%;
      max-width: 500px;
    }

    .login-form h2 {
      margin-bottom: 20px;
    }

    button[type="submit"] {
      width: 100%;
      padding: 10px;
      font-size: 18px;
      color: #fff;
      background-color: #000;
      cursor: pointer;
      border: 1px solid transparent;
    }

    button[type="submit"]:hover {
      color: #000;
      background-color: #fff;
      border: 1px solid #dcc;
    }

    input {
      width: 100%;
      margin-bottom: 20px;
      padding: 10px;
      border: 1px solid #ccc;
    }

    label {
      margin-bottom: 10px;
      display: inline-block;
    }

    /* Chat Widget
       ========================================================================== */

    .chat-widget {
      position: absolute;
      bottom: 20px;
      right: 60px;
      border: 1px solid #ccc;
      height: 500px;
      width: 350px;
      display: flex;
      flex-direction: column;
    }

    .chat-header {
      border-bottom: 1px solid #ccc;
      padding: 10px 15px;
      display: flex;
      justify-content: space-between;
      align-items: center;
    }

    .chat-header h2 {
      font-size: 20px;
    }

    .end-chat {
      background: transparent;
      border: none;
    }

    .chat-messages {
      padding: 15px;
      flex-grow: 1;
      list-style: none;
    }

    .chat-messages li {
      margin-bottom: 10px;
    }

    .message-input {
      margin-bottom: 0;
      border: none;
      border-top: 1px solid #ccc;
    }

    .notice {
      display: none;
    }

    .dialog-container {
      position: absolute;
      top: 0;
      right: 0;
      bottom: 0;
      left: 0;
      background-color: rgba(0, 0, 0, 0.8);
      display: flex;
      justify-content:center;
      align-items: center;
    }

    .dialog {
      width: 500px;
      background-color: white;
      display: flex;
      align-items:  center;
    }

    .dialog-form {
      width: 100%;
      margin-bottom: 0;
      padding: 20px;
    }

    .dialog-form > * {
      display: block;
    }

    .submit-btn {
      color: #5C8436;
      background-color: #181919;
      width: 100%;
    }

    .submit-btn:hover {
      color: #5C8436;
      background-color: #222;
    }

Create a basic chat application

This next step involves creating a simple interface with which a potential customer will interact with a support agent. Open up frontend/src/App.js and change it to look like this:

    // frontend/src/App.js

    import React from 'react';
    import { handleInput, joinChat, sendMessage, endChat, sendTranscript } from './methods.js';
    import { ToastContainer } from 'react-toastify';

    import 'react-toastify/dist/ReactToastify.min.css';
    import './App.css';

    class App extends React.Component {
      constructor() {
        super();
        this.state = {
          showTranscriptDialog: false,
          transcriptEmail: "",
          username: "",
          currentRoom: null,
          currentUser: null,
          messages: [],
          newMessage: "",
        }

        this.handleInput = handleInput.bind(this);
        this.joinChat = joinChat.bind(this);
        this.sendMessage = sendMessage.bind(this);
        this.endChat = endChat.bind(this);
        this.sendTranscript = sendTranscript.bind(this);
      }

      render() {
        const { currentUser, messages, newMessage, showTranscriptDialog } = this.state;

        const messageList = messages.map(message => {
          const arr = message.parts.map(p => {
            return (
              <span className="message-text">{p.payload.content}</span>
            );
          });

          return (
            <li className="message" key={message.id}>
              <div>
                <span className="user-id"><strong>{message.sender.name}: </strong></span>
                {arr}
              </div>
            </li>
          )
        });

        return (
          <div className="App">
            {!currentUser ? (
              <div className="login-form">
                <h2>Chat with a Support Agent</h2>
                <form onSubmit={this.joinChat}>
                    <label htmlFor="username">Enter your username</label>
                    <input onChange={this.handleInput} type="text" id="username" name="username"
                      placeholder="Username" />
                      <button type="submit">Start chatting!</button>
                    </form>
                  </div>
            ) : (
              <div className="chat-widget">
                <header className="chat-header">
                  <h2>Support</h2>
                  <button onClick={this.endChat} className="end-chat">
                    End Chat
                  </button>
                </header>
                <ul className="chat-messages">
                  {messageList}
                </ul>

                <form onSubmit={this.sendMessage} className="message-form">
                  <input
                    className="message-input"
                    autoFocus
                    name="newMessage"
                    placeholder="Compose your message and hit ENTER to send"
                    onChange={this.handleInput}
                    value={newMessage}
                  />
                </form>
              </div>
              )}

              <ToastContainer />

              {showTranscriptDialog ? (
                <div className="dialog-container">
                  <div className="dialog">
                    <form className="dialog-form" onSubmit={this.sendTranscript}>
                      <label htmlFor="email">Send a transcript of the chat to the following email address:</label>
                      <input onChange={this.handleInput} type="email" id="email" name="transcriptEmail"
                        placeholder="name@example.com" />
                      <button type="submit" className="submit-btn">
                        Send transcript
                      </button>
                      </form>
                    </div>
                  </div>
              ) : null}
          </div>
        );
      }
    }

    export default App;

Create a new methods.js file within the src directory and add the following code to it:

    import axios from 'axios';
    import { ChatManager, TokenProvider } from '@pusher/chatkit-client'
    import { toast } from 'react-toastify';
    import randomWords from 'random-words';

    function handleInput(event) {
      const { value, name } = event.target;

      this.setState({
        [name]: value
      });
    }

    function addSupportStaffToRoom() {
      const { currentRoom, currentUser } = this.state;

      return currentUser.addUserToRoom({
        userId: "support",
        roomId: currentRoom.id
      });
    };

    function createRoom() {
      const { currentUser } = this.state;

      currentUser
        .createRoom({
          name: randomWords({ exactly: 2, join: ' ' }),
          private: true
        })
        .then(room => connectToRoom.call(this, room.id))
        .then(() => addSupportStaffToRoom.call(this))
        .catch(console.error);
    };

    function connectToRoom(id) {
      const { currentUser } = this.state;

      return currentUser
        .subscribeToRoomMultipart({
          roomId: `${id}`,
          messageLimit: 100,
          hooks: {
            onMessage: message => {
              this.setState({
                messages: [...this.state.messages, message]
              });
            },
          }
        })
        .then(currentRoom => {
          this.setState({
            currentRoom
          });
        });
    }

    function joinChat(event) {
      event.preventDefault();

      const { username } = this.state;

      if (username.trim() === "") {
        alert("A valid username is required");
      } else {
        axios
          .post("http://localhost:5200/users", { username })
          .then(() => {
            const tokenProvider = new TokenProvider({
              url: "<your token provider endpoint>"
            });

            const chatManager = new ChatManager({
              instanceLocator: "<your chatkit instance locator>",
              userId: username,
              tokenProvider
            });

            return chatManager.connect().then(currentUser => {
              console.log(currentUser);
              this.setState(
                {
                  currentUser,
                },
                () => createRoom.call(this)
              );
            });
          })
          .catch(console.error);
      }
    }

    function sendMessage(event) {
      event.preventDefault();
      const { newMessage, currentUser, currentRoom } = this.state;

      if (newMessage.trim() === "") return;

      currentUser.sendSimpleMessage({
        roomId: `${currentRoom.id}`,
        text: newMessage
      });

      this.setState({
        newMessage: "",
      });
    }

    function endChat(event) {
      event.preventDefault();

      this.setState({
        showTranscriptDialog: true
      });
    }

    function sendTranscript(event) {
      event.preventDefault();

      const { currentRoom, currentUser, transcriptEmail } = this.state;

      axios.post("http://localhost:5200/transcript", {
        roomId: currentRoom.id,
        email: transcriptEmail,
        name: currentUser.name,
      })
        .then(res => {
          toast.success("Transcript sent successfully!");

          this.setState({
            showTranscriptDialog: false,
            transcriptEmail: "",
          })
        })
        .catch(err => {
          console.error(err);
          toast.error("An problem occured");
        })
        .finally(() => {
          currentUser.disconnect();
          this.setState({
            currentUser: null,
            currentRoom: null,
            messages: [],
            newMessage: "",
          })
        });
    }

    export {
      handleInput,
      joinChat,
      sendMessage,
      endChat,
      sendTranscript,
    }

Don’t forget to replace the <your token provider endpoint> and <your chatkit instance locator> placeholders above with the appropriate values from your Chatkit dashboard.

Here’s a quick run down on what the code above does:

  • Once a user connects to the Chatkit instance, a new room is created for the interaction through the createRoom() method.
  • Once the user is connected to the room, the support staff agent is also added to the room instantaneously. In a real world application, you will probably have several support agents, so there will be a (hopefully short) waiting time for the user before they are connected to an available agent.
  • Messages can now be sent back and forth between the current user and the support agent. You can navigate to the Console tab on the instance dashboard to add a message to the room as the Support agent.
  • Once the chat is ended, a new dialog will appear prompting the user to enter an email address where the transcript will be sent.
  • The sendTranscript() function makes a request to the /transcript endpoint on the server, and passes along the email address along with the room’s ID.
  • If you look at the /transcript endpoint on the server, you will see that it simply fetches the messages in the room, and constructs some HTML which is then sent to the provided email address via SendGrid’s API.

Here’s how the above process looks like in practice:

Wrap up

In this tutorial, we covered how to send chat transcripts with Chatkit and Sendgrid. We covered a simple use case but you can take it further by customizing the transcript email template or creating an archive of all your chats which can come in handy if you need to keep a record of past chats on file for all of your agents.

You can checkout other things Chatkit can do by viewing its extensive documentation. Don’t forget to grab the full source code used in this tutorial here.

#reactjs #Sendgrid #javascript #Chatkit

How to Send Emails Using Twilio Sendgrid in Laravel 8

Laravel email works over a popular mailer library that is the SwiftMailer. This is an inbuilt library in Laravel. It allows us to integrate several mail drivers for sending emails. You can use SMTP and API based drivers to send emails in Laravel. I already shared tutorials for integrating the SMTP like Gmail and Mailgun. But, today, in this post, I will show you the integration of Twilio Sendgrid with Laravel 8. The SendGrid is an email service. By using the Sendgrid, you can send emails, marketing campaigns such as automation, etc. Also, it provides the features to track sent emails, activities on email like open, click, etc. So, let’s create a new project in Laravel 8 and integrate this SendGrid SMTP to send emails.

Prerequisites

Before creating this project, please make sure you have the below tools in your system. We are going to create a Laravel 8 project. Hence, you must have the specified version of these tools.

  • PHP >= 7.3
  • MySQL (version > 5)
  • Apache/Nginx Server
  • VS Code Editor
  • Composer

#Laravel 8 #Integrate SendGrid in Laravel #Laravel 8 SendGrid #SendGrid Email Tracking #SendGrid SMTP Integration #SendGrid SMTP Settings

Jessica Smith

Jessica Smith

1612606870

REAL TIME CHAT SOLUTIONS SERVICES FOR MOBILE APPS

Build a Real Time chat application that can integrated into your social handles. Add more life to your website or support portal with a real time chat solutions for mobile apps that shows online presence indicators, typing status, timestamp, multimedia sharing and much more. Users can also log into the live chat app using their social media logins sparing them from the need to remember usernames and passwords. For more information call us at +18444455767 or email us at hello@sisgain.com or Visit: https://sisgain.com/instant-real-time-chat-solutions-mobile-apps

#real time chat solutions for mobile apps #real time chat app development solutions #live chat software for mobile #live chat software solutions #real time chat app development #real time chat applications in java script

Alex  Sam

Alex Sam

1576484092

Drive Engagement and Interaction Voluntarily via Team Collaboration Chat Apps

Emails are almost extinct. The need to stay glued to your office desk is no more a necessity to stay connected with teams. Chat applications are here and are changing the way teams collaborate and communicate with each other with increased mobility.

Chats have gone a long way from being reserved only for socializing purposes to hosting important team discussions and meetings where ideas are born and rolled out. Team chat apps built for iOS and Android devices are the new collaborative tools that business people thrive on.

Chat apps solutions are seeing technical teams in technology companies, be it startups or an enterprise-grade companies as early adopters as they have started realizing the benefits of flexible and frictionless communication that these chat solutions power.

Advantages that Pose Real-time Instant Messaging Apps as Convenient Alternatives for Group or Team Communication Over Conventional emailing Systems

1. Ad-hoc Conversations
Apart from bringing employees together chat apps pave way for grouping teams for ad-hoc conversations where technical people can discuss over tasks, brainstorm and come up with ideas.

2. Epicenter of Tasks
Through an array of integrations that chat applications offer, teams, especially those involved in product development, can centralize their accounts on other collaborative platforms like GitHub, Jira into the chat application itself creating an ecosystem that caters to all collaboration purposes.

3. Record Keeping and Easy Search
Key developments that happen over a verbal discussion need to be noted down else chances are more likely for losing a crucial breakthrough achieved over a brainstorming session. Team collaboration chat apps record every improvement and contents that dates back to any time can be fully searched.

4. Switch Over Devices Based on Convenience
Multi device compatibility ensures that your employees are connected with teams no matter what devices they are using. If on-the-go connectivity is your preference, get things done on smartphone. If convenience matters the most, switch over to your desktop and continue from where you left.

5. Multiple Communication Medium
Text messages, voice calls, video calls, VOIP calls, direct messages, group chats on iOS and Android extend the modes and medium through which you can get to communicate with your peers, teams and entire organization for that matter.

6. Everything Else that Count
Adding to these, features like file sharing (multiple file types), video conferencing, opinion generation through polls, task delegation, followups, update, personalized notification settings, reminders, to-do list creation and much more can be done through real-time team chat applications.

However, the limitations of team collaboration chat apps end here only if you think so. With every other team, apart from development teams, like those that operational level, management level, marketing level etc can also get to reap the benefits of chat apps. Read on to know the

Instances Which Chat Apps Prove Useful for All Teams in an Organization

Why restrict the benefit of real-time instant messaging chat app to only technology teams into development and designing. Every other team in your office or organization can get a fair share of its advantages.

Here are some of the instances where chat apps can be useful for other teams.
Human Resource team can build employee engagement programs. HRs can get fast response from employees, build a powerful relationship with them, conduct opinion poll for decision making. The hardly-used suggestion box in office premises can be replaced by a chat app for a more effective and instant feedback.

An organization’s system administration team can stay connected with employees on the go and be there on time to resolve issues. Moreover, notifications on breakdowns and other technical issues can help in saving the downtime. Alerts and reminders on instant messaging applications can contribute towards proactive care.

For marketing professionals and sales executives, chat apps on multiple platforms like iOS, Android can reduce series of mail threads into chat logs that are easily searchable. Live video calls and voice calls can help them build better client relationship and both pre and post sales support can get more livelier and personalized with chat apps.

At operational level, chat apps can connect an organization’s representative with many third party vendors to keep up on timely delivery, maintenance, bill payments and more.

Group or Team collaboration applications are the new age communication tools that can contribute for successful communication between employees of an organization in multiple angles. From initiating an idea to getting works done, real time chat apps have started helping organization at many instances which are tough to handle when done conventionally.

If you are into an organization but still have not got a chat app on board, it is high time that your build a chat app on iOS and Android.

#Team Collaboration Chat Apps #real time chat apps #build a chat app #real-time instant messaging chat app #Chat apps solutions

How much does an iOS & Android chat app cost to make?

Messaging is one of the most essential functions that smartphone users want to have at hand. Smartphone won’t be a must in our life if it has no chatting function. There is no one that doesn’t have WhatsApp, Viber, WeChat or Snapchat installed on his device. AppClues Infotech has a relevant experience crafting different messaging apps with top-notch technology stacks behind them, and we want to share our insights with you.

We have a team of professionals who are highly talented Chat App Developers, experienced Whatsapp clone app developers who works hard on simple as well as complex problem and give their best out of it. Our Chat highly experienced app developers design an application which are elegant, feasible, easy accessible and capability to generate high traffic towards your website.

Ideal features in a Chat app:

  • Instant Messaging
  • Real time connectivity
  • Multimedia file transmission
  • Security
  • Push Notification
  • Quick search
  • Group Chat
  • Video and voice calling
  • Social Integration

The Cost to build an Chat app is between $15 to $30 per hour. The Cost is depends on complexity of a product and feature we need in chat app. The following three factors affect the final cost:

  • Technical complexity
  • The number of devices and OS
  • Custom designs and animations

Benefits with AppClues Infotech:

  • Steady Mobile Chat App Development Service : Our chatting app development services aim at kickstarting and concluding the app development tasks reliably.
  • Affordable Chatting App Development : It is our vision AppClues Infotech to concentrate on the chat mobile app designing and development in the most affordable way.
  • Guaranteed WhatsApp Chat Clone Security : The specialization of our experts lies in securing the apps with some of the most robust features.
  • Quick Client Support : We at AppClues Infotech take it as our responsibility to provide quick client support in any of the ways required to them.

With its years of expertise in developing messaging/ chatting apps, the AppClues Infotech team of developers has now endeavored into chatting app development. Our sole aim with the messaging apps development is to bring people closer with instant messaging facilities. The app developers at our company have helped us achieve the goal with utmost delicacy.

#chat app development company #best chatting app development company for android or ios #android chat app development company #ios chat app development company #instant messaging app development #how much does it cost to develop a chat app