Adding new integrations

Tyler Crammond edited this page Dec 7, 2018 · 29 revisions

This is a by example type of tutorial about how to add integration of a new tool to Toggl Button Chrome extension.

We'll go through the process of adding an integration for a service named "SuperCoolTool" (with url https://www.supercooltool.com) to Toggl Button.

Whenever contributing to the project, please remember to follow the Contributing Guidelines.

Clone and set up the Toggl Button repo

git clone git@github.com:toggl/toggl-button.git

Please follow set up instructions found in the README.

Add reference of the new tool

We need to add a reference to origins.json file located in src/scripts. This reference will be picked up by the extension and used when requesting permissions to run inside the tool's webpage.

Add a new entry. Try to keep the alphabetical order. It should look something like this:

'supercooltool.com': {
  'url': '*://*.supercooltool.com/*',
  'name': 'Supercooltool'
},

If your tool does not have public url that people use it with, please leave the url parameter empty.

Note that the name property is used to fetch the file we'll create in next step.

  • If name is "Super Cool Tool" it will translate to super-cool-tool.js.
  • If name is "SuperCoolTool" it will translate to supercooltool.js.

and so on ...

Create a content script for the integration

Create a file in 'src/scripts/content/'. In our case it is named supercooltool.js

This is the script that determines where the Toggl Button is displayed on the page and how it functions.

The script should look something like this:

'use strict';
/* global togglbutton, $ */

togglbutton.render(
  '#task-view:not(.toggl)',
  { observe: true },
  $container => {
    const descriptionSelector = () => {
      const $description = $('#task-title', $container);
      return $description.textContent.trim();
    }

    const projectSelector = () => {
      const $project = $('#task-project span', $container);
      return $project.textContent.trim();
    }

    const tagsSelector = () => {
      const $tags = $('.tag-list', $container);
      return ($tags.textContent || '').split(',').map(tag => tag.trim());
    }

    const link = togglbutton.createTimerLink({
      className: 'super-cool-tool',
      description: descriptionSelector,
      projectName: projectSelector,
      tags: tagsSelector
    });

    $('.toolbar').appendChild(link);
  }
);

Let's go through it step by step:

Render

#task-view(.toggl) - This is the selector of the container that must be visible when adding Toggl Button link. Note the :not(.toggl), this prevents the extension adding a button multiple times to the page.

If the Toggl Button is shown inside of a popup view, this should be the selector of this popup view. From this part of the page, all relevant information will be fetched.

{observe: true} - This can be one of two values {} or {observe: true}.

Observe true means that the extension observes the page for dynamic data loading. This means that if the tool loads some parts of the page with ajax or renders dynamically, the Toggl Button extension waits until all loading is done before inserting a button into the page. This is usually essential for single page applications.

It's good practice to retrieve the data we need using functions that are passed to Toggl Button, rather than providing static string values. In our example, these are the functions named descriptionSelector, etc.

This allows the extension to retrieve the data at the moment the user clicks the button, rather than only once on page load. (Again, especially important for single page applications).

$('#task-title', $container) - We find the element that contains the description we want to use for our time entry, inside the "container" we chose in the first parameter of togglbutton.render(). It's usually best to include the reference to the container, but in some cases the layout of the page may prevent this.

We do the same in our projectSelector and tagsSelector. The tags selector does some transformation of the value, as toggl button expects an array of tags rather than a comma-delimited string.

You'll probably need to tweak these selectors according to the service you are integrating with. Some services won't have any concept of tags or labels, in which case it can be ignored.

Link
  • className - this should be same as the name of the tool
  • description - this is the function to find the description value that was set in the previous section
  • project - this is the function to find the project value that was set in the previous section
  • tags - this is the function to find the array of tags we found in the previous section
const link = togglbutton.createTimerLink({
  className: 'super-cool-tool',
  description: descriptionSelector,
  projectName: projectSelector,
  tags: tagsSelector
});

There is a buttonStyle option you can use. If you pass 'minimal' to this option, only the button icon will be displayed, the text 'Start Timer' will not be included.

Toggl button location

The .toolbar class is a container to which we append the Toggl Button link.

$('.toolbar').appendChild(link);

Try to respect the layout around the button, and avoid interfering with features of the service.

Custom styles

If you want to add some custom styles to your Start timer link you can add it to style.css. Just create new style rule with selector:

/********* SUPERCOOLTOOL *********/
.toggl-button.super-cool-tool {

}   

and add all needed styles in it.

Update README.md

Add your integration to the list of compatible services.

- [SuperCoolTool](https://www.supercooltool.com/)

Opening the pull request

If you have done all that you are ready to submit a pull request.

Please don't forget to refer to the Contributing Guidelines.

It would be great if you would add a screenshot and description of where in the tool the toggl button link should be visible. This simplifies the review progress for Toggl Button maintainers. If all is good, it will be merged shortly.

Please squash all your commits into one commit. This keeps the git log more compact and clear.

You can’t perform that action at this time.
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.
Press h to open a hovercard with more details.