Mattermost Platform

Mattermost plugins: The web app

The web app side lets your plugins change the layout and user experience of Mattermost

(Originally published at controlaltdieliet.be)

This is the fourth installment in a series of articles on Mattermost plugins. First, we talked about how to set up your developer environment. We then examined the structure of server-side and web app plugins before walking through how to build a server-side plugin in Mattermost. In this piece, we’ll explore how to create web app plugins.

The web app is written in JavaScript. It uses Redux, and you can write your plugin in Typescript as well. In this article, we’ll use JavaScript. By the end of this article, you’ll add an item to the menu and an icon to the channel header.

I made a git-repository from the Mattermost Starter Template Plugin because it is minimalistic and is a good place to start. My repository contains a branch for each additional step. The Mattermost demo plugin gives a very nice overview. It can be overwhelming for the first time, but it is a good reference. I also recommend taking a look at the Mattermost Developer Plugins Reference or the Todo bot as a starting point.

Install some dependencies

Assuming you’ve already followed the steps from my previous articles, you’ve already have a server app. Now, we’re going to add the web app part (even though you can write plugins that have just a server part or just a web app part).

Run git checkout origin/webapp_step1 to see the code. You’ll see a new folder called webapp plugin.

Because we removed the web app in a previous version, there is no build in the Makefile. So, you need to generate a new Makefile. In the code you downloaded, this is already done for you. But you also have to install some dependencies:

npm install --save-dev @babel/core @babel/preset-env @babel/preset-react babel-loader webpack webpack-cli
npm install --save react
Web app folder

A closer look into the webapp folder

Let’s take a look at the webapp folder. The i18n folder will contain the translated strings for your app. We will not use this in this tutorial. And we can ignore the tests folder as well.

The node_modules folder contains the necessary nodejs modules for building your app. You’ll write your code in the src folder, but we will get back to that later.

The webpack.config.js is important. Around line 37 you’ll find module.exports = {entry: [ 'src/index.js'].... This line defines where your code for your web app starts. If you start your web app plugin in index.txs or start.js, you’ll have to modify this line or your web app plugin will be empty.

The web app folder

The index.js file

We start with a minimal index.js file.

In the repository, this is branch webapp_step2. Use git checkout origin/webapp_step2 to load the code.

First, we load React. Then we define a class plugin. The code in the function will run when the plugin gets enabled. You have to register your plugin with the unique ID that you also defined in the plugin.json file as we described here.

import React from 'react';

class HelloWorldPlugin {
    initialize(registry, store) {
    console.log("Hello there in the console");        
    }

}
window.registerPlugin('be.controlaltdieliet.demoortom.first_mattermost_plugin', new HelloWorldPlugin());

When you enable the plugin, you will see this in your console:

Mattermost plugin console

Add a button to the channel header

From now on, you can start implementing all the cool stuff that you find in the web app reference. Let’s add a button to the top of every channel that says hello when you click it.

In the repository, this is branch webapp_step3. Run git checkout origin/webapp_step3 to load the code:

import React from 'react';
const Icon = () => 
<i className='icon fa fa-plug'/>;
class HelloWorldPlugin {
    initialize(registry, store) {
        registry.registerChannelHeaderButtonAction(
            // icon - JSX element to use as the button's icon
            ,
            // action - a function called when the button is clicked, passed the channel and channel member as arguments
            // null,
            () => {
                alert("Hi there");
            },
            // dropdown_text - string or JSX element shown for the dropdown button description
            "Says hello",
        );
    }
}
            
window.registerPlugin('be.controlaltdieliet.demoortom.first_mattermost_plugin', new HelloWorldPlugin());
Mattermost web app plugins

Add an item to the Main Menu

You can add an item to the Main Menu in just a few lines.

In the repository, this is branch webapp_step4. Run git checkout origin/webapp_step4 to load the code:

registry.registerMainMenuAction(
  "Saying hi",
  () => alert("Hi again"),
);
Mattermost web app Main Menu

Create a React component

While showing alerts is fun, we can do more. Let’s create a component that you will add to the left channel panel. For this, we need to create a React component.

To do that, create a new folder called components in your src folder. In this new folder, create another folder called my_first_component. In this folder, create a file called index.js.

Next, import React and create a class called MyFirstComponent and render some HTML code into it. Run git checkout origin/webapp_step4 to retrieve the code in your folder:

import React from 'react'

export default class MyFirstComponent extends React.PureComponent {
    render() {
        const iconStyle = {
            display: 'inline-block',
            margin: '0 7px 0 1px',
        };
        const style = {
            margin: '.5em 0 .5em',
            padding: '0 12px 0 15px',
            backgroundColor: 'rgba(255,255,255,0.6)',
        };
        const url= "https://developers.mattermost.com/extend/plugins/webapp/reference"
        return (
              

              <i
                    className='icon fa fa-plug'
                    style={iconStyle}
                />
                <a href={url}>More info on plugins</a<

        );
    }
}

Display the component in the channel sidebar

Now, in the index.js that’s located in the webapp/src folder, import your first component and add it to the left sidebar. You can see this in the branch webapp_step5. Use git checkout origin/webapp_step5 to see the code:

import MyFirstComponent from './components/my_first_component'
const Icon = () => <i className='icon fa fa-plug'/>;
class HelloWorldPlugin {
    initialize(registry, store) {
        const {leftsidebarheader}=registry.registerLeftSidebarHeaderComponent(MyFirstComponent)
Left sidebar in Mattermost

Toggle the right sidebar

We created a new component RightSideFolder in the components folder. This component will be shown in the right sidebar.

First, import the component the same as you did with your MyFirstComponent. Next, register it with registry.registerRightHandSidebarComponent. This will return a variable that tells you if the sidebar is shown or not.

After that, bind it to the channel header button with store.dispatch(toggleRHSPlugin). When you click the channel header button, you’ll receive a well-deserved applause!

Use git checkout origin/webapp_step6 to load the code:

import React from 'react';
import RightSideBar from './components/right_hand_sidebar'
import MyFirstComponent from './components/my_first_component'
      
const Icon = () => <i className='icon fa fa-plug'/>;
class HelloWorldPlugin {
    initialize(registry, store) {
        registry.registerMainMenuAction(
            "Saying hi",
            () => allert("Hi again"),
        );
              
        registry.registerChannelHeaderButtonAction(
            ,
            () => store.dispatch(toggleRHSPlugin),
            "Says hello",
        );
      
        const {toggleRHSPlugin} = registry.registerRightHandSidebarComponent(
            RightSideBar,"Applause!");
              
        const {leftsidebarheader}=registry.registerLeftSidebarHeaderComponent(MyFirstComponent)
    }
}
      
window.registerPlugin('be.controlaltdieliet.demoortom.first_mattermost_plugin', new HelloWorldPlugin());
Mattermost web app plugins

Start building your own plugins!

Congratulations!

You made it to the end of this series and should be able now to start building your own plugins.

Since you’ve made it the far, perhaps you’re interested in my previous series on Mattermost integrations:

mm

Tom De Moor is the official reviewer of the Dutch translation of Mattermost. He is a technology lover with a broad outlook who uses PHP, Python, NodeJS, MariaDB, MongoDB, and Raspberry Pis on a daily basis. He is also an official drone pilot.