Skip to content

Integrate with other apps

lramos edited this page Apr 15, 2015 · 4 revisions

There are some interfaces that need to be implemented in order to integrate Schedulizer with other external apps. The external app must have an authentication endpoint and a way to autocomplete the name of other users. Optionally it may have a way to post messages in groups (which allows the Remind Users feature to work).

Follow these steps to integrate with your app:

(1) Add your app name to the ExtAppType enum at src/main/java/com/yammer/schedulizer/auth/ExtAppType.java. For example:

public enum ExtAppType {
    yammer, facebook, myApp
}

(2) Create inside /src/main/java/com/yammer/schedulizer/auth an Authenticator for your app. For example: MyAppAuthenticator.java. It should extend ExtAppAuthenticator and implement the method getTokenOwner that receives an access token from your external app, makes a request to get the users information and returns an Employee instance. For example:

package com.yammer.schedulizer.auth;

import com.fasterxml.jackson.databind.JsonNode;
import com.sun.jersey.api.client.Client;
import com.yammer.schedulizer.entities.Employee;

import javax.ws.rs.core.MediaType;

public class MyAppAuthenticator extends ExtAppAuthenticator {
    private static final String MY_APP_CURRENT_USER_ENDPOINT = "https://my_app.com/me";
    private static final String ACCESS_TOKEN_PARAM = "access_token";

    public MyAppAuthenticator(Client client) {
        super(client);
    }

    @Override
    public Employee getTokenOwner(String accessToken) {
        JsonNode response = client.resource(MY_APP_CURRENT_USER_ENDPOINT)
                .queryParam(ACCESS_TOKEN_PARAM, accessToken)
                .accept(MediaType.APPLICATION_JSON_TYPE)
                .get(JsonNode.class);

        String myAppId = response.get("id").asText();
        String name = response.get("name").asText();
        String imageUrlTemplate = response.get("image_url").asText();

        Employee employee = new Employee(name, myAppId, ExtAppType.myApp);
        employee.setImageUrlTemplate(imageUrlTemplate);
        return employee;
    }
}

(3) Now that the back end is all set, you must go to the front end. First you should add any necessary javascript sdk loading and initialization at the src/main/resources/com/yammer/schedulizer/freemarker/ext_app_config.ftl. For example, add the lines:

<#elseif extApp == "myApp">
    <script src="https://my_app.com/sdk.js"></script>
    <script>
       myApp.init('${extAppClientId}');
    </script>

(4) Now you should implement the request to your app endpoints. Do that by editing the file src/main/resources/assets/js/services/ext_app_api.js and adding your app to the big switch. Note that the map EXT_APP_TYPES comes from the backend, so your app is already an entry.

        case EXT_APP_TYPES.myApp:
            if (!myApp) { throw new Error('Could not load myApp api'); }
            extAppApi =  {
                // A me function
                getLoginStatus: function(callback) {
                    // get the login status and if user is logged return the user information to the callback
                    callback({
                        access_token: "access_token_got_from_the_app",
                        user: {
                            id: 1,
                            photo: 'users_photo_url',
                            full_name: 'Users full name'
                        }
                    });
                },
                login: function(callback){  
                    // login to the app
                    callback({
                        access_token: "access_token_got_from_the_app",
                        user: {
                            id: 1
                        }
                    });
                },
                autocomplete: function(prefix, callback, autocompleteType) {
                    if (autocompleteType === 'user') {
                        // search for user name that start or contain the prefix
                        var users = [
                            {
                                id: 1,
                                photo: 'photo_url_user1',
                                full_name: 'User 1 that starts with prefix'
                            },
                            {
                                id: 2,
                                photo: 'photo_url_user2',
                                full_name: 'User 2 that starts with prefix'  
                            }
                        ];
                        callback(users);
                    } else if (autocompleteType === 'group') {
                        // search for user name that start or contain the prefix
                        var groups = [
                            {
                                id: 1,
                                photo: 'photo_url_group1',
                                full_name: 'Group 1 that starts with prefix'
                            },
                            {
                                id: 2,
                                photo: 'photo_url_group2',
                                full_name: 'Group 2 that starts with prefix'  
                            }
                        ];
                        callback(groups);
                    }
 
                },
                post: function(groupId, message, tagList, callback) {
                    // this method should post the passage to the group with id groupId
                    // message is a text with {0}, {1}, and so on at the users name position
                    // {0} refers to tagList[0], {1} to tagList[1] and so on.
                    // you should replace these {i} with the given tags
                    // An auxiliar method called formatString is already implemented (see the yammer implementation of the post function)
                    callback("post_url");
                }
            };
            break;

At each one of these functions, the callback must be called.

ps: If your app does not support group posting, that is fine.. just set post to undefined:

post: undefined
Clone this wiki locally