A Complete Project

This tutorial will touch on many of the other tutorials. Refer to these for more information: Get started, Instant Messaging and Single Sign-On.

This tutorial aims to give you a better understanding of the process of adding Weavy to an existing host application, but your use-case will probably not look exactly like this one. Similarly, all applications will impose it's own set of design decisions and technical limitations. This should only be treated as an example.

The following steps are involved in this tutorial:

  • Plan for integrating Weavy components
  • Find and include the Weavy javascript library script.
  • Configure and add the Weavy client.
  • Add apps.
  • Configure Single Sign-On.
You can download the complete source for this example from here. You need to make a few changes for everything to work - consult the readme.txt file in the zip-package. Setup and access through your IIS.

Scenario

You work for a company that sells a CRM system called Grip.

Your boss asked you to put together a live demo of Weavy integrated in Grip. He gave you this list of things to do:

  • Add Weavy instant messaging on all pages.
  • Display a files app on the customer overview page.
  • Enable and configure single sign-on.

Let's get to it! You have a job to do!

Planning

We need to figure out where the Weavy building blocks should be added in Grip. Which UI elements do we need to add? How can we best present the information from Weavy?

This is what Grip looks like:

Our goal here is to add the Weavy components in a way that feels seamless and fits well with our host application.

On the customer overview page, we are asked to add a files app for uploading and creating new files. Looking at the application it seems that the best place to put it is to simply add a new box below the customer address:

Looking at the top, we already have a notifications icon. That would be a good place to add an additional icon for the Weavy Messenger. A red dot signals unread conversations and clicking the icon will slide out the Messenger:

Ok, so we have a plan!

Implementation

Next steps will be to progressively add functionality and building blocks until everything is in place. We will start by adding the Weavy javascript library and the client-side script needed, then some custom CSS and finally add Single Sign-on to complete the project.

You'll need to work with both the Client and Server SDK, so if you haven't already, start by forking our weavy-sln repo.

Adding the Weavy javascript library

Everything starts with the Weavy javascript library - it needs to be added to your application or website in order for Weavy to work. To obtain a copy of the Weavy javascript library you should point your browser to the client configurator in your Weavy installation, i.e. https://{weavyurl}/client.

You will be presented with a form where you can configure the client SDK. As you can see the URL to the client SDK can be modified to get different configurations of the SDK. In this case you should de-select all checkboxes except Bundle jQuery. Don't enter anything for Global name.

Now copy the script for Plain HTML and inject it somewhere in your application or website. It should look something like this:

<script src="https://{weavyurl}/javascript/weavy.jquery.js"></script>

Adding the Weavy Messenger

So, now when the Weavy javascript library is added, we can add the markup we need, instantiate a new Weavy client and load the messenger.

We'll start with adding two elements to our markup.

First, an icon that's added next to the existing notification icon in the top bar, so that we can toggle the messenger. Add the CSS class toggle-messenger to the li element, so that we can target it later on.

Let's also add a plain div that we can style and that will contain the markup of the messenger panel. Add an id or class attribute, so that we can reference the element later when we create the Weavy client.

The markup should look something like this:

<li class="notification-list topbar-dropdown d-lg-block toggle-messenger">
    <button class="nav-link dropdown-toggle arrow-none btn btn-link">
        <i class="dripicons-message noti-icon"></i>
    </button>
    <!-- Containter for messenger -->
    <div id="weavy-messenger-container"></div>
</li>

Add the CSS below to make the panel slide in from the right.

#weavy-messenger-container {
    position: fixed;
    top: 70px;
    bottom: 0;
    z-index: 1000;
    transition: transform, opacity;
    transition-duration: 0.2s;
    transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
    right: 0;
    width: 20rem;
    transform: translateX(20rem);
    pointer-events: none;
}

.show #weavy-messenger-container {
    transform: none;
    border-left: 1px solid #ccc;
    border-top: 1px solid #ccc;
}

Add the script below somewhere after the Weavy javascript library is loaded.

var weavy = new Weavy({
    jwt: generateJWT("unique-username", "user@example.com")
});

// get or create the global space
var space = weavy.space({key: "global" });

// get or create the messenger app
var messengerApp = space.app({key: "main-messenger", type: "messenger", container: "#weavy-messenger-container" });

The code above will instantiate a new Weavy client and create or retrieve a space named global. Then, a new messenger app will be created or retrieved and associated with that space. All markup will be injected into the div with id #weavy-messenger-container that we added earlier.

Don't worry about the jwt option at this point, we'll go through that in the Single Sign-On section.

It's recommended to instantiate the Weavy client after the HTML document is loaded and parsed, e.g. after jquery.ready or DOMContentLoaded.

Next we need to hook up an event handler to toggle the messenger when clicking the icon.

// toggle messenger
$(document).on("click", ".toggle-messenger", function () {
    $(this).hasClass("show") ? $(this).removeClass("show") : $(this).addClass("show");
});
This example uses jQuery to hook up to the click event, but you are free to use vanilla javascript or any other javascript framework.

Let's also add an event handler for the Weavy badge event. The event is triggered whenever the number of unread conversations change and when the client is loaded for the first time.

When there are unread conversations we will add the has-unread CSS class to the messenger icon, which we will style later to display a little round dot overlaying the icon.

// hook up to the badge event to indicate if user has unread conversations
weavy.on("badge", function (e, data) {
    data.conversations === 0 ? $(".toggle-messenger").removeClass("has-unread") : $(".toggle-messenger").addClass("has-unread");
});

That should be it! Weavy messenger is added to Grip ;-)

Adding the Files App

Next order of business is to add the files app to the customer overview page. The files app lets users preview, download and upload a wide variety of file formats.

Start by adding an element to your markup where you want the files app to appear. Give it a classname or id, so that you can target it when adding the app.

<div id="weavy-files-container"></div>

Next, you need some mechanism to detect when to load the files app and also (atleast) in a real world implementation, a unique id you can use for the key option when creating the files app.

In this example we will be looking for a data-attribute named customer-id. If it exists, we will add the app and use the customer id to create a unique key for this customer. The javascript could look something like this:

// customer overview "detection"
var customerId = $(".section-customer").data("customer-id");

if (customerId && customerId.length) {
    // add the files app for this context
    space.app({key: "files-" + customerId, type: "files", container: "#weavy-files-container"});
} else {
    // we are not on the customer overview page - do nothing more
}

After a simple test to determine if we are in fact on a customer overview page, the files app is created and added to the DOM.

That's it! We should now have a files app that is displayed when users visits a customer overview page in Grip, allowing our customers to see and upload new documents that are related to the customer.

Single Sign-On

As a last step we are adding SSO to seamlessly sign in Grip users into Weavy. We are going to be creating and passing JSON Web Tokens (JWT) to securly send the needed information between the host application and Weavy.

You can read more about the SSO authentication flow in our single sign-on tutorial.

Configure a Client

The first thing to do is to create a client in Weavy that holds the secret that should be used when signing and validating tokens. The secret is used by the host application (Grip in this case) when signing the JWT and also by Weavy when validating the JWT. Hence, the secret that you decide to use must be identical and configured both in the Weavy client and in the method you use for creating tokens.

If you are following along with this example you will need to create the following Weavy client:

client id = GripCMS
client secret = only_for_demo_purposes

Creating a JSON Web Token

For every request in the host application where Weavy is loaded and initialized, you should create a JWT token and pass it as an option to the Weavy client. Depending on what technologies your host application is based on, there are a number of libraries that can you with the creation of a JWT token. Take a look at the jwt.io page for more information.

For this tutorial you can generate the JWT token from your client script. You will need a JWT library for javascript. You can use any javascript library listed at jwt.io or you can download the source for this tutorial where a suitable library is included. (See download link at top of document)

In production, tokens must be created on the server side! Generating tokens using client side scripting will expose the secret string.

In this example, we are using the jsrsasign library to create the token.

// IMPORTANT! 
// Tokens should never by created with client side scripting!
// The code below is only an example used for demo purposes!
function generateJWT(id, email) {
    var secretString = "only_for_demo_purposes";

    // token generation courtesy of https://github.com/kjur/jsrsasign
    // see https://jwt.io for a available libraries

    // token valid for 2 hours
    var dateSoon = new Date();
    dateSoon.setHours(dateSoon.getHours() + 2);

    // return the signed token
    return KJUR.jws.JWS.sign(null, 
      { 
        alg: "HS256", 
        typ: "JWT" 
      }, 
      {       
        iss: "Grip", 
        client_id: "GripCMS", 
        sub: id, 
        exp: dateSoon.getTime() / 1000,      
        email: email      
      }, 
      secretString);
}

Conclusion

Hopefully this has given you an idea on how you can plan for and integrate Weavy features into your application!

Below you can find the complete script and CSS for this project or you can download the complete source for this example from here

$(function () {

    var weavy = new Weavy({
        jwt: generateJWT("unique-userid", "user@example.com")
    });

    // get or create the global space
    var space = weavy.space({key: "global" });

    // get or create the messenger app
    var messengerApp = space.app({key: "main-messenger", type: "messenger", container: "#weavy-messenger-container" });

    // toggle messenger
    $(document).on("click", ".toggle-messenger", function () {
        $(this).hasClass("show") ? $(this).removeClass("show") : $(this).addClass("show");
    });

    // hook up to the badge event to indicate if user has unread conversations
    weavy.on("badge", function (e, data) {
        data.conversations === 0 ? $(".toggle-messenger").removeClass("has-unread") : $(".toggle-messenger").addClass("has-unread");
    });

    // customer overview "detection"
    var customerId = $(".section-customer").data("customer-id");

    if (customerId && customerId.length) {
        // add the files app for this context
        space.app({key: "files-" + customerId, type: "files", container: "#weavy-files-container"});
    } else {
        // we are not on the customer overview page - do nothing more
    }
});

// IMPORTANT! 
// Tokens should never by created with client side scripting!
// The code below is only an example used for demo purposes!
function generateJWT(sub, email) {
    var secretString = "only_for_demo_purposes";

    // token generation courtesy of https://github.com/kjur/jsrsasign
    // see https://jwt.io/ for a available libraries

    // token valid for 2 hours
    var dateSoon = new Date();
    dateSoon.setHours(dateSoon.getHours() + 2);

    // return the signed token
    return KJUR.jws.JWS.sign(null, 
      { 
        alg: "HS256", 
        typ: "JWT" 
      }, 
      { 
        iss: "Grip", 
        client_id: "GripCMS",
        sub: id, 
        exp: dateSoon.getTime() / 1000,      
        email: email      
      }, 
      secretString);
}
#weavy-messenger-container {
    position: fixed;
    top: 70px;
    bottom: 0;
    z-index: 1000;
    transition: transform, opacity;
    transition-duration: 0.2s;
    transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
    right: 0;
    width: 20rem;
    transform: translateX(20rem);
    pointer-events: none;
}

.show #weavy-messenger-container {
    transform: none;
    border-left: 1px solid #ccc;
    border-top: 1px solid #ccc;
}

#weavy-files-container {
    width: 100%;
    height: 500px;
}

.has-unread {
    position: relative;
}

.has-unread::after {
    content: '';
    position: absolute;
    top: 1.5rem;
    right: .5rem;
    width: .5rem;
    height: .5rem;
    background-color: #fa5c7c;
    border-radius: 50%;
}