Custom Widget Tutorial
This page walks you though the steps for building a custom widget. We decided to cover a very simple case: a sample widget that displays profile information for a user in GitHub. This widget doesn't perform any complex operations, like authentication and authorization in a third-party service, nor does it have complex style elements. Still, we hope that this tutorial helps you grasp the basic concept behind a custom widget.
This tutorial describes the following steps:
- Building the widget manifest
- Creating an entry point for your widget
- Writing a script for the widget
- Testing the widget
- Uploading the widget to YouTrack
- Uploading the widget to the JetBrains Plugins Repository
Create the Widget Manifest
As the first step, we create the manifest.json
file. This file defines the attributes for the custom widget.
For YouTrack Standalone to read and display the attributes in the widget manifest:
The file must be named
manifest.json
.The file must be stored in the top-most level of the ZIP archive.
Here is the manifest file for our sample widget:
{
"key": "github-user-widget",
"version": "0.0.1",
"name": "GitHub User Information",
"description": "Widget shows information about GitHub user.",
"author": "anonymous",
"products": {
"Hub": ">=2018.1",
"YouTrack": ">=2018.1"
}
}
Our widget manifest contains definitions for just a few attributes. For a complete list of the attributes that you need to define in the manifest file, see Widget Manifest.
Create an index.html File
Second step is to create an entry point for your widget: an index.html
file. This is a standard HTML5 file. Here, we include a reference to the hub-dashboard-addons
library. This library allows communication between the widget and the page that it is plugged into in YouTrack. The file also contains CSS styles that manipulate the presentation of data retrieved from the GitHub profile. The body
element includes the widget script itself (index.js
).
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<!-- Default styles of dashboard widgets -->
<link rel="stylesheet" type="text/css" href="https://unpkg.com/hub-dashboard-addons@latest/dashboard.css">
<!-- Include dashboard connector from CDN -->
<script src="https://unpkg.com/hub-dashboard-addons@latest"></script>
<style>
.user-avatar {
width: 64px;
height: 64px;
}
</style>
</head>
<body>
<div id="user-details">Loading...</div>
<script src="index.js"></script>
</body>
</html>
Create the Script
The third step is to create the script itself. In our case, the script retrieves and displays the user profile of a specified GitHub user.
/* Declare a constant that contains a login of the target github user */
const USER_NAME = 'jetbrains';
/* The following renderUserDetails(user) function creates and inserts the user profile data into the DOM */
function renderUserDetails(user) {
const container = document.getElementById('user-details');
container.innerHTML = `
<img src=${user.avatar_url} class="user-avatar"/>
<h4>${user.name} aka <a href="${user.html_url}">${user.login}</a></h4>
<div>
<div>Followers: ${user.followers}</div>
<div>Repos: ${user.public_repos}</div>
`;
}
/* The following function actually retrieves the data from GitHub using the GitHub API.
It uses the Fetch API (https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API) */
function loadAndRenderUser(userLogin) {
return fetch(`https://api.github.com/users/${userLogin}`)
.then(response => {
return response.ok ? response.json() : new Error(response);
})
.then(user => {
renderUserDetails(user);
return user;
})
.catch(err => console.warn(err));
}
/* The last step is to register the widget in the dashboard and initiate loading the user data.
Also, this block defines displayed widget title and adds the refresh button.
When you click the refresh button, the script will reload and re-render the user profile data.
We use Dashboard API to implement this functionality. */
// Register widget:
Dashboard.registerWidget(function (dashboardAPI, registerWidgetAPI) {
// Load GitHub profile data
loadAndRenderUser(USER_NAME)
// Set the widget title
.then(user => dashboardAPI.setTitle(`GitHub User ${user.login}`));
// Add the refresh button.
registerWidgetAPI({
onRefresh: () => loadAndRenderUser(USER_NAME)
});
});
Test the Widget
To test the widget, we need to load it in the Widgets Playground. First, we run a static server on the local directory with the custom widget files. In our case, we use npm http-server that requires Node.js. To simplify the matters even more, we use a YouTrack Standalone service that is available over HTTP. If you have YouTrack Standalone running over HTTPS, then you need to host your widget over HTTPS as well. In this case, you can use a service like https://ngrok.com
. For more information, see Testing Widgets over a Secure Connection.
To serve the widget over HTTP:
Install the HTTP server:
npm i http-server -g
From the custom widget directory, run the HTTP server with the following command:
The HTTP server starts and serves the content on the current directory. In the response, you see the IP addresses (both internal and external) at which the HTTP server is accessible. For example:http-server . --cors -c-1 -p 9033
We run the YouTrack service locally, so we can load the widget into the widgets playground from the http://localhost:9033/
address.
To load your widget in the widgets playground:
- Open the Widgets Playground page in YouTrack.
In the Server Settings section of the Administration menu, select Custom Widgets.
Click the Widgets playground link in the header.
Enter the web address for your custom widget in the input field. In our case,
http://localhost:9033/
- Click the Load widget button.
The widget is loaded and displayed in the widgets playground.
If you modify the code and upload these changes to your web server, use the Reload widget button to refresh the widget content and test the updates.
Upload the Widget
Now that we successfully tested the widget in the playground, we can upload it to the production environment.
First, we create a ZIP archive with the widget files. You can use any archive application to your liking. Just remember that manifest.json
and index.html
files must be located on the top-most level of the zip file.
For example, we used command line prompt in macOS to create the archive. Our sample widget contains only three files and all of them are located in the same directory without any subdirectories. Thus the command to create the archive is very simple (run in the custom widget directory):
zip custom-widget.zip *
We created the custom-widget.zip
file. Now we just need to upload it to the production environment:
To upload your widget:
Open the Custom Widgets page in YouTrack.
- Click the New widget... button.
The New widget dialog is open in the side bar.
- Select the ZIP archive to upload.
The information from the
manifest.json
file is shown in the sidebar.
- Click Upload widget button.
The widget is uploaded to the server and displayed in the list of available custom widgets. It also appears in the Add widget drop-down menu on dashboards:
That's it! Users can add the new custom widget to their dashboards in YouTrack.
Upload the Widget to the JetBrains Plugins Repository
The final and optional step is to share your widget with other companies who are working with YouTrack by uploading your widget to the JetBrains Plugins Repository.
To upload your widget to the repository:
In your web browser, access the JetBrains Plugins Repository.
- Click the Sign In button in the header.
If you already have a JetBrains Account, enter your email address and password.
If you don't have a JetBrains Account, register with your email address and create an account.
- From the header, select
The YouTrack Widgets page opens.
. - Click the Upload Widget button in the header.
The Adding new widget page opens.
Select a Category from the drop-down list.
Click the Choose File button and select the ZIP archive that contains your custom widget.
- Click the Upload New Plugin button.
Your custom widget is uploaded to the JetBrains Plugins Repository.
When a moderator has reviewed the widget and approved it for publication, the widget is added to the directory.