How to Add an Icon in Systray in Odoo 17

How to Add an Icon in Systray in Odoo 17

If you are working with Odoo custom modules and want to improve the user interface, one of the most practical things you can do is add custom icons in the systray. In this guide, we will walk through how to add an icon in systray in Odoo 17 by creating a complete custom module, writing the necessary JavaScript (OWL), XML templates, and CSS, and then explaining the logic behind each part of the code.

This approach is developer-friendly, SEO-optimized, and follows the modern Odoo 17 web client architecture. By the end of this tutorial, you will have a fully functional system tray icon that displays dynamic data (meeting count, in our case) and opens the calendar when clicked.

Step-by-Step Guide: How to Add an Icon in Systray in Odoo 17

Now let’s dive into the actual process. We’ll create a custom module that displays a new icon in the systray.

Step 1: Understanding the Goal

Before jumping into code, let’s clarify what we want to achieve:

  • Add a custom icon in Odoo’s systray (top right corner of the web client).
  • Fetch dynamic data using Odoo services (orm and action).
  • Display a badge counter (e.g., meeting count).
  • On click, redirect the user to the calendar view.
  • Make sure the module is clean, reusable, and developer-friendly.

This kind of feature is useful when you want quick access to notifications, pending tasks, or alerts directly from the top bar of Odoo.

Step 2: Create a Custom Module Structure

Let’s create a new custom module called calendar_systray_icon. The basic module folder structure will look like this:

calendar_systray_icon/
│
│── __init__.py
│── static/
│   └── src/
│       ├── js/
│       │   └── calendar_systray.js
│       ├── xml/
│       │   └── calendar_systray.xml
│       └── css/
│           └── calendar_systray.scss
└── __manifest__.py
JSON

Step 3: Define the Module Manifest

# How to Add an Icon in Systray in Odoo 17

{
    "name": "Calendar Systray Icon",
    "version": "17.0.1.0.0",
    "summary": "Add a calendar icon in systray with meeting counter",
    "description": """
        This module demonstrates how to add an icon in systray in Odoo 17.
        It shows the meeting count dynamically and redirects to calendar view.
    """,
    "category": "Tools",
    "author": "Your Name",
    "license": "LGPL-3",
    "depends": ["web", "calendar"],
    "assets": {
        "web.assets_backend": [
            "calendar_systray_icon/static/src/js/calendar_systray.js",
            "calendar_systray_icon/static/src/xml/calendar_systray.xml",
            "calendar_systray_icon/static/src/css/calendar_systray.scss",
        ],
    },
    "installable": True,
    "application": False,
}
Python

Step 4: JavaScript (OWL Component)

In calendar_systray.js, We’ll add the logic for the systray icon.

/** @odoo-module */

import { registry } from "@web/core/registry";
import { Component, useState, onWillStart } from "@odoo/owl";
import { useService } from "@web/core/utils/hooks";

export class CalendarSystray extends Component {
    static template = "calendar.CalendarSystray";
    static props = {};

    setup() {
        this.action = useService("action");
        this.orm = useService("orm");
        this.state = useState({
            meetingCount: 0,
            loading: true,
        });

        onWillStart(async () => {
            await this.loadMeetingCount();
        });
    }

    async loadMeetingCount() {
        try {
            const count = await this.orm.call("res.users", "systray_get_activities", []);
            const calendarGroup = count.find(group => group.type === "meeting");
            this.state.meetingCount = calendarGroup ? calendarGroup.meetings.length : 0;
        } catch (error) {
            console.error("Error loading meeting count:", error);
            this.state.meetingCount = 0;
        } finally {
            this.state.loading = false;
        }
    }

    onClick() {
        this.action.doAction("calendar.action_calendar_event", {
            additionalContext: {
                default_mode: "day",
                search_default_mymeetings: 1,
            },
            clearBreadcrumbs: true,
        });
    }
}

registry.category("systray").add("calendar.CalendarSystray", {
    Component: CalendarSystray,
    isDisplayed: (env) => {
        return env.services.user.hasGroup("base.group_user");
    },
}, { sequence: 30 });
JavaScript

Explanation:

  • useService("orm"): Calls Odoo models.
  • useService("action"): Triggers Odoo actions.
  • onWillStart: Lifecycle hook to load data before rendering.
  • this.state: Reactive state to hold meeting count.
  • onClick: Redirects to the calendar when the icon is clicked.
  • registry.category("systray").addRegisters the component in the system tray.

Step 5: XML Template

In calendar_systray.xml:

<?xml version="1.0" encoding="UTF-8"?>
<templates>
    <t t-name="calendar.CalendarSystray" owl="1">
        <div class="o_systray_item o_calendar_systray" role="button" t-on-click="onClick">
            <div class="o_calendar_systray_icon">
                <i class="fa fa-home" title="Calendar"/>
                <span t-if="state.meetingCount > 0" class="o_calendar_systray_badge">
                    <t t-esc="state.meetingCount"/>
                </span>
            </div>
        </div>
    </t>
</templates>
XML

Explanation:

  • fa fa-home: Font Awesome icon (you can replace it with any other).
  • t-if Ensures the badge only appears if the meeting count is greater than 0.
  • t-esc: Displays the meeting count dynamically.

Step 6: CSS Styling

In calendar_systray.scss:

.o_calendar_systray {
    cursor: pointer;
    padding: 8px;
    transition: background-color 0.2s ease;
    position: relative;
    
    &:hover {
        background-color: rgba(0, 0, 0, 0.1);
    }
    
    .o_calendar_systray_icon {
        display: flex;
        align-items: center;
        justify-content: center;
        width: 32px;
        height: 32px;
        position: relative;
        
        .fa-home {
            font-size: 18px;
            color: rgba(255, 255, 255, 0.9);
            transition: color 0.2s ease;
        }
        
        .o_calendar_systray_badge {
            position: absolute;
            top: 2px;
            right: 0;
            background-color: #e74c3c;
            color: white;
            border-radius: 50%;
            min-width: 16px;
            height: 16px;
            display: flex;
            align-items: center;
            justify-content: center;
            font-size: 11px;
            line-height: 1;
            padding: 0 4px;
            box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3);
        }
    }
    
    &:hover .o_calendar_systray_icon .fa-home {
        color: #ffffff;
    }
}
CSS

Explanation:

  • Adds hover effect.
  • Style the badge as a small red circle.
  • Makes the icon visually appealing and noticeable.

Step 7: Installing the Module

  1. Place the module in your Odoo custom addons directory.
  2. Restart your Odoo server: ./odoo-bin -c odoo.conf -u calendar_systray_icon
  3. Activate developer mode.
  4. Install the module from the Apps menu.

Once installed, you will see a calendar icon with a counter in your Odoo systray.

Step 8: Testing the Feature

How to Add an Icon in Systray in Odoo 17
  • Create some calendar events for the logged-in user.
  • Refresh your Odoo instance.
  • The systray icon should now display the number of meetings.
  • Clicking on the icon should redirect you to the Calendar app with your meetings filtered.

Related Blogs:

>> How to Add a Custom Filter in Odoo

>> What is Odoo Runbot and How to Access It?

>> How to Add a Button to the Action Menu in Odoo 17

Final Thoughts

Adding systray icons in Odoo 17 is a great way to improve usability and provide quick access to important information. In this article, we built a complete custom module to demonstrate how to add an icon in systray in Odoo 17, including JavaScript logic, XML templates, CSS styling, and asset management.

By customizing this code, you can create systray icons for notifications, reminders, approvals, or any other real-time information your business needs.

If you’re an Odoo developer, this approach will become handy whenever clients ask for quick shortcuts or personalized notifications in the Odoo web client.

Leave a Comment

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.