Skip to content

How to: Add New Integration

Artem edited this page Dec 8, 2023 · 6 revisions

This article explains how you can add a new timer integration with a web app that is not yet supported by TMetric.

The primary way to add an integration is to contribute to this repository. Just follow the instructions below.

But what if you have your custom private web app? We won't add it to our repository and using the extension in a development mode is a lame option.

We provide a way to support your private system. If that's your case refer to How to: Integrate TMetric with Private Web App article.

Objective

Add the Start Timer button to an issue page of the virtual Web app called BigIssueTrac.

The following picture is an example of how the Start Timer button looks in Trello.

Trello

Preparing for development

  1. Fork the tmetric-plugins repo. See Fork A Repo article if you've never done this before.
  2. Install Node.js
  3. Open the project's folder and build the project by running the following script.
$ npm install
$ npx gulp

If you are building on Windows you can simply run build.bat.

Writing code

TMetric browser extension as well as sample code is written in TypeScript.

1. Create an empty integration

The code inserting the timer button into a Web page runs as content script.

Create bigIssueTrac.ts file in src/in-page-scripts/integrations/ folder with a following content.

class BigIssueTrac implements WebToolIntegration {
    /**
     * The array of URLs (with wildcards) that are used to identify
     * pages as those that belong to the service.
     */
    matchUrl = [
    ];

    /**
     * If the service may be on a custom domain implement this method
     * to identify pages of the service by other features (e.g. meta-tags).
     */
    match(source: Source) {
        return false;
    }

    /**
     * Extracts information about the issue (ticket or task) from a Web
     * page by querying the DOM model.
     */
    getIssue(issueElement: HTMLElement, source: Source): WebToolIssue {
        return undefined;    
    }

    /**
     * Inserts the timer button for the identified issue into a Web page.
     */
    render(issueElement: HTMLElement, linkElement: HTMLElement) {
    }
}

IntegrationService.register(new BigIssueTrac());

2. Add the description of integration

  1. Add bigIssueTrac.svg logo (size is 400x160) to the src/images/integrations/ folder
  2. Add description to array of descriptions stored in items variable in the src/background/webToolDescriptions.ts file
{
    serviceType: 'BigIssueTrac',
    serviceName: 'Big Issue Trac',
    icon: 'bigIssueTrac.svg',
    origins: ['https://*.bigIssueTrac.com/*'],
    scripts: {
        js: ['in-page-scripts/integrations/bigIssueTrac.js']
    }
}

The sample is not the full webToolDescriptions.ts.

3. Implement integration's methods

When you implement the WebToolIntegration interface the final version of bigIssueTrac.ts may look like the following code.

class BigIssueTrac implements WebToolIntegration {

    /**
     * The array of URLs (with wildcards) that are used to identify
     * pages as those that belong to the service.
     */
    matchUrl = [
        '*://*.bigissuetrac.com/issues/*'
    ];

    /**
     * If the service may be on a custom domain implement this method
     * to identify pages of the service by other features (e.g. meta-tags).
     */
    match() {
        return $$.getAttribute('meta[name=application-name]', 'content') == 'BigIssueTrac';
    }

    /**
     * The identifier of the element, which contains the task details
     * and inside which the button will be rendered.
     */
    issueElementSelector = [
        '.ticket'
    ];

    /**
     * Extracts information about the issue (ticket or task) from a Web
     * page by querying the DOM model.
     */
    getIssue(issueElement: HTMLElement, source: Source) {

        const issueId = $$.try('.ticket-id', issueElement).textContent;
        const issueName = $$.try('.ticket-name', issueElement).textContent;
        const serviceUrl = source.protocol + source.host;
        const issueUrl = source.path;
        const projectName = $$.try('.project-name', issueElement).textContent;
        const tagNames = $$.all('.labels', issueElement).map(label => label.textContent);
        const serviceType = 'BigIssueTrac'

        return {
            issueId, issueName, issueUrl, projectName, serviceUrl, serviceType, tagNames
        } as WebToolIssue;
    }

    /**
     * Inserts the timer button for the identified issue into a Web page.
     */
    render(issueElement: HTMLElement, linkElement: HTMLElement) {
        const host = $$('.link-list', issueElement);
        if (host) {
            const container = $$.create('li');
            container.appendChild(linkElement);
            host.appendChild(container);
        }
    }
}

IntegrationService.register(new BigIssueTrac());

Submitting code to the main repo

  1. After you test the new integration and make sure it's working properly, list the supported system in the Supported services section on the README.md file.
  2. Please use git squash and merge all your commits into one. This helps keeping the Git log more compact and clear.
  3. Open a Pull Request
Clone this wiki locally