Origami Frontend Components & Services

Readme: o-comment-api

A JavaScript API that provides a simple abstraction of the FT's commenting APIs.

This modules communicates with backend services:

Contents

Prerequisites

Global configuration

This module uses global configuration. These are related to Livefyre and the connection details to the backend services.

The default configuration is the production one:

{
    "suds": {
        "baseUrl": "//session-user-data.webservices.ft.com",
        "endpoints": {
            "livefyre": {
                "init": "/v1/livefyre/init",
            },
            "user": {
                "updateUser": "/v1/user/updateuser",
                "getAuth": "/v1/user/getauth"
            }
        }
    },
    "ccs": {
        "baseUrl": "http://comment-creation-service.webservices.ft.com",
        "endpoints": {
            "getComments": "/v1/getComments",
            "postComment": "/v1/postComment"
        }
    },
    "cacheConfig": {
        "authBaseName": "comments-prod-auth-",
        "initBaseName": "comments-prod-init-"
    },
    "livefyre": {
        "networkName": "ft"
    }
}

In order to change to the settings of the TEST environment, then this configuration should be used:

{
    "suds": {
        "baseUrl": "//test.session-user-data.webservices.ft.com"
    },
    "ccs": {
        "baseUrl": "http://test.comment-creation-service.webservices.ft.com"
    },
    "cacheConfig": {
        "authBaseName": "comments-test-auth-",
        "initBaseName": "comments-test-init-"
    },
    "livefyre": {
        "networkName": "ft-1"
    }
}

There are two ways for changing the environment:

Declaratively

In order to change the configuration, you can add a script tag in your page source with the format in the example below:

<script data-o-comment-api-config type="application/json">
    {
        "suds": {
            "baseUrl": "//test.session-user-data.webservices.ft.com"
        },
        "ccs": {
            "baseUrl": "http://test.comment-creation-service.webservices.ft.com"
        },
        "cacheConfig": {
            "authBaseName": "comments-test-auth-",
            "initBaseName": "comments-test-init-"
        },
        "livefyre": {
            "networkName": "ft-1"
        }
    }
</script>

This configuration will be loaded on the o.DOMContentLoaded event.

Imperatively

oCommentApi.setConfig(config)

The configuration can be changed be using the setConfig static method. Calling this method with an object will merge the current configuration with the object specified (deep merge, primitive type values of the same key will be overwritten).

Example:

oCommentApi.setConfig({
    "suds": {
        "baseUrl": "//test.session-user-data.webservices.ft.com"
    },
    "ccs": {
        "baseUrl": "http://test.comment-creation-service.webservices.ft.com"
    },
    "cacheConfig": {
        "authBaseName": "comments-test-auth-",
        "initBaseName": "comments-test-init-"
    },
    "livefyre": {
        "networkName": "ft-1"
    }
});

As on the event o.DOMContentLoaded the widgets declared in the DOM are automatically initialized, it is preferred to call this function before the o.DOMContentLoaded event is triggered.

API

Data APIs

oCommentApi.api.getLivefyreInitConfig

This method communicates directly with the 'livefyre/init' endpoint of SUDS. It accepts a configuration object and a callback as paramaters. A Livefyre object is passed into the callback (both init and auth fields).

Configuration
Mandatory fields:
Optional fields:
Example
oCommentApi.api.getLivefyreInitConfig({
    elId: 'dom-id',
    articleId: 'art15123',
    url: 'http://example.com/article/art15123',
    title: 'Article title'
}, function (err, data) {
    if (err) {
        throw err;
    }

    // do something with the data
});
Sample response

Successful request:

{
    "init": {
        "app": "main",
        "articleId": "4ec7810a-797f-11e1-8fad-00144feab49a",
        "el": "livefyre-app-ft-4ec7810a-797f-11e1-8fad-00144feab49a",
        "siteId": "304428",
        "collectionMeta": "eyJhbGciOiJIUzI1NiJ9.eyJjaGVja3N1bSI6ImYyYjViZDgyNjIxMWQ1ZDg4ZmI1ZjllYWUyZTI1NDcxIiwiYXJ0aWNsZUlkIjoiNGVjNzgxMGEtNzk3Zi0xMWUxLThmYWQtMDAxNDRmZWFiNDlhIiwidGl0bGUiOiJMaXZlZnlyZSB0ZXN0IHBhZ2UgLSBGVC5jb20iLCJ1cmwiOiJodHRwOi8vd3d3LmZ0LmNvbS9jbXMvcy8wLzRlYzc4MTBhLTc5N2YtMTFlMS04ZmFkLTAwMTQ0ZmVhYjQ5YS5odG1sIiwidHlwZSI6ImxpdmVjb21tZW50cyIsInN0cmVhbV90eXBlIjoibGl2ZWNvbW1lbnRzIiwidGFncyI6WyJzZWN0aW9ucy5Db21wYW5pZXMiLCJzZWN0aW9ucy5GaW5hbmNpYWxzIiwic2VjdGlvbnMuRmluYW5jaWFsIFNlcnZpY2VzIiwic2VjdGlvbnMuVVMgXHUwMDI2IENhbmFkaWFuIENvbXBhbmllcyJdfQ.VexpwSe72aPB-CEDxiyFT4QDjFEh3PGHgkkVjiHXhXY",
        "checksum": "f2b5bd826211d5d88fb5f9eae2e25471",
        "disableAvatars":true
    },
    "auth": {
        "token": "eyJhbGciOiJIUzI1NiJ9.eyJkb21haW4iOiJmdC1pbnQtMC5meXJlLmNvIiwiZXhwaXJlcyI6MTQwMTgxMDI3NDI2MywidXNlcl9pZCI6Ijg5NDg3NDM5IiwiZGlzcGxheV9uYW1lIjoicm9saSJ9.u2ko_UkQkkFwL20RvfMnGmi9ZPXxsnUuxWH5MnAoeyI",
        "expires": 1401810274263,
        "displayName": "pseudonym",
        "settings": {
            "emailcomments": "hourly"
            "emailreplies": "immediately"
            "emaillikes": "never"
            "emailautofollow": "off"
        }
    }
}

If the article based on the articleId and the article's metadata cannot be classified to an internal section of Livefyre:

{
    "init": {
        "unclassifiedArticle": true
    }
}

For examples of the auth object please see the getUserData method.

For more information on the possible init fields of Livefyre, please visit: http://docs.livefyre.com/developers/reference/livefyre-js/#conv-config-object

For more information on auth tokens, please visit: http://docs.livefyre.com/developers/user-auth/remote-profiles/ and http://docs.livefyre.com/developers/getting-started/tokens/auth/

For more information on user settings, please visit: http://docs.livefyre.com/product/features/user-options/email-notifications/#UserEmailOptions and http://docs.livefyre.com/developers/user-auth/remote-profiles/#ping-for-pull

api.getUserData

This method gets the authentication data and user settings. This data is needed for actions that require the user to be authenticated.

Configuration
Optional fields:
Example

Normal access, without forcing:

oCommentApi.api.getUserData(function (err, data) {
    if (err) {
        throw err;
    }

    // do something with the data
});

With force set to true:

oCommentApi.api.getUserData({
    force: true
},
function (err, data) {
    if (err) {
        throw err;
    }

    // do something with the data
});
Sample response

User is logged in, successful request:

{
    "token": "eyJhbGciOiJIUzI1NiJ9.eyJkb21haW4iOiJmdC1pbnQtMC5meXJlLmNvIiwiZXhwaXJlcyI6MTQwMTgxMDI3NDI2MywidXNlcl9pZCI6Ijg5NDg3NDM5IiwiZGlzcGxheV9uYW1lIjoicm9saSJ9.u2ko_UkQkkFwL20RvfMnGmi9ZPXxsnUuxWH5MnAoeyI",
    "expires": 1401810274263,
    "displayName": "pseudonym",
    "settings": {
        "emailcomments": "hourly"
        "emailreplies": "immediately"
        "emaillikes": "never"
        "emailautofollow": "off"
    }
}

User is not logged in or the user's session is expired:

null

User is logged in, but doesn't have a pseudonym set:

{
    pseudonym: false
}

The authentication service that SUDS is using is down:

{
    serviceUp: false
}

api.updateUser

Updates the user's details in both Livefyre and FT Membership systems (DAM).

Data needed

For more details on the email options visit http://answers.livefyre.com/product/features/user-options/email-notifications/#UserEmailOptions

All fields are optional, but there should be provided at least one.

Example
oCommentApi.api.updateUser({
    pseudonym: 'my name',
    emailcomments: 'hourly',
    emailreplies: 'immediately',
    emaillikes: 'never'
},
function (err, data) {
    if (err) {
        throw err;
    }

    // do something with the data
});
Sample response

Successful response:

{
    status: "ok"
}

Response with an error:

{
    status: "error",
    error: "Error message."
}

api.getComments

Gets the comments of an article together with collection ID, max event ID (used in Livefyre's system when streaming new data) and authentication data.

Configuration
Mandatory fields:
Optional
Example
oCommentApi.api.getComments({
    articleId: 'art15123',
    url: 'http://example.com/article/art15123',
    title: 'Article title'
}, function (err, data) {
    if (err) {
        throw err;
    }

    // do something with the data
});
Sample response
{
    "collection": {
        "unclassified": false,
        "collectionId": "91440735",
        "lastEvent": 1411541039265900,
        "comments": [{
            "parentId": "",
            "author": {
                "displayName": "roli main",
                "tags": ["FT"],
                "type": 1
            },
            "content": "<p>comment</p>",
            "timestamp": 1411541039,
            "commentId": "216743299",
            "visibility": 1
        }],
        "totalPages": "6"
    }
}
Automatic streaming

If stream: true is set, the same callback will be used to generate streaming events.

The response will be in the following form:

{
    "stream": {{streaming object}}
}

For more information about the streaming object mentioned above, see the Streaming section

api.postComment

This is a method with which a comment can be posted to an article's collection.

Configuration
Mandatory fields
oCommentApi.api.postComment({
    collectionId: 1525234,
    commentBody: "This is a comment"
}, function (err, data) {
    if (err) {
        throw err;
    }

    // do something with the data
});
Sample response

Successful response:

{
    "success": true,
    "status": "ok",
    "code": "200",
    "invalidSession": false,
    "errorMessage": null,
    "bodyHtml": "<p>post comment</p>",
    "commentId": "215819761",
    "createdAt": 1411370210
}

Response with an error:

{
    "success": false,
    "status": null,
    "code": null,
    "invalidSession": false,
    "errorMessage": "As good as it may be, you can't post the same comment twice.",
    "bodyHtml": null,
    "commentId": null,
    "createdAt": 0
}

api.deleteComment

This is a method with which a comment can be posted to an article's collection.

Configuration
Mandatory fields
oCommentApi.api.deleteComment({
    collectionId: 1525234,
    commentId: 16482
}, function (err, data) {
    if (err) {
        throw err;
    }

    // do something with the data
});
Sample response

Successful response:

{
    "success": true,
    "invalidSession": false,
    "errorMessage": null
}

Response with an error:

{
    "success": false,
    "invalidSession": false,
    "errorMessage": "You don't have permission to delete this comment."
}

api.stream.create

If you want to get any changes in real-time, you can create a streaming channel.

In order to do that, you should call the following function:

api.stream.create(collectionId, {
    callback: function (data) {},
    lastEventId: 5132356345234
});

Configuration options:

Note: For optimization purposes, if a stream already exists for a given collectionId, that stream will be reused, and the provided callback will be added to the callback list of that stream.

Limitation: lastEventId is not considered if a stream already exists for a given collectionId.

api.stream.destroy

If a stream is not needed anymore, it can be destroyed.

api.stream.destroy(collectionId);

api.stream.destroy(collectionId, {
    callback: existingCallbackReference
});

api.stream.destroy(collectionId, existingCallbackReference);

The only mandatory parameter is collectionId.
There are two possibilities:

Sample responses
New comment
{
    comment: {
        parentId: "1468854",
        author: {
            displayName: "user1",
            tags: ["FT"],
            type: 1
        },
        content: "<p>this is a test comment</p>",
        timestamp: 1426860385,
        commentId: "284661456",
        visibility: 1
    }
}
Comment updated
{
    comment: {
        updated: true,
        commentId: "284661456",
        content: "<p>this is a test comment updated</p>"
    }
}
Comment deleted
{
    comment: {
        deleted: true,
        commentId: "284661456"
    }
}
Posting new comments enabled/disabled
{
    collection: {
        commentsEnabled: true
    }
}

Caching

An optional cache is available to store information in the browser, data like article metadata (information which is needed for Livefyre), user authentication details, Livefyre tokens. If the cache is not enabled, these information will be fetched from the backend services on each request.

Enable caching

In order to enable caching, you should set some module level configuration (any approach mentioned in the 'Global configuration' chapter works):

Example:

oCommentApi.setConfig({
    "cache": true
});

Clear the cache

The cache layer uses sessionStorage API to store data. While this is cleared automatically each time the browser is closed, there could be some situations the cache should be cleared explicity.

The cache layer provides a public clear method which will delete all o-comments-api related cache entries from the sessionStorage.

oCommentApi.cache.clear();

There's a possibility to clear just the auth or Livefyre init cache:

oCommentApi.cache.clearAuth();
oCommentApi.cache.clearLivefyreInit();

Logging

Logging can be enabled for debugging purposes. It logs using the global 'console' if available (if not, nothing happens and it degrades gracefully).
By default logging is disabled.

oChat.enableLogging()

This method enables logging of the module.

oChat.disableLogging()

This method disables logging of the module.

oChat.setLoggingLevel(level)

This method sets the logging level. This could be a number from 0 to 4 (where 0 is debug, 4 is error), or a string from the available methods of 'console' (debug, log, info, warn, error).
Default is 3 (warn).

Browser support

Works in accordance with our support policy

Core/Enhanced Experience

Works only in enhanced experience, or with the polyfill service on older browsers.

Switch component view

GitHub Repository

Install o-comment-api

If using the Build Service, add o-comment-api@^2.5.0 to your script tag.

If running a Manual Build, run bower install --save "o-comment-api@^2.5.0".

Help & Support

o-comment-api is maintained directly by the Origami team. If you have any questions about o-comment-api or Origami in general, we are happy to help. 😊

Slack: #ft-origami
Email: origami.support@ft.com

Feedback / Issues

To report a bug or request features please create an issue on Github. For support or general feedback please get in touch 😊

Slack: #ft-origami
Email: origami.support@ft.com