creating a custom tabList (nav menu) based on teams

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • jamie
    Senior Member
    • Aug 2025
    • 163

    #1

    creating a custom tabList (nav menu) based on teams

    We need to customize the top menu, also known as the nav menu or tab list, based on a user’s team.

    We don’t just want to show or hide items, since that keeps the same structure; we need to modify its configuration.

    The Deep Wiki AI suggests this is possible, but it seems a bit questionable to me.

    Has anyone else done this?
  • rabii
    Active Community Member
    • Jun 2016
    • 1354

    #2
    i guess you will need to rewrite you own custom navbar class - look at this class

    EspoCRM – Open Source CRM Application. Contribute to espocrm/espocrm development by creating an account on GitHub.
    Rabii
    EspoCRM & Web Dev

    🔗 See what I’ve built for EspoCRM

    Comment

    • emillod
      Active Community Member
      • Apr 2017
      • 1529

      #3
      Yep, it's possible, we've added for example help icon to show sidepanel with bug form report Click image for larger version

Name:	image.png
Views:	0
Size:	4.0 KB
ID:	123199

      Comment

      • jamie
        Senior Member
        • Aug 2025
        • 163

        #4
        Originally posted by rabii
        i guess you will need to rewrite you own custom navbar class - look at this class

        https://github.com/espocrm/espocrm/b...navbar.js#L492
        i ended up doing it via a javascript override


        Code:
        define('custom:menu', [], function () {
        class User {
        async getUserTeamID() {
        try {
        const response = await fetch('api/v1/App/user');
        const data = await response.json();
        return data.user.defaultTeamName;
        } catch (error) {
        console.error('Failed to fetch user data:', error);
        return null;
        }
        }
        }
        return User;
        });
        let tabList = [];
        window.addEventListener('popstate', () => {
        if (tabList.length > 0) {
        replaceNavTabs(tabList);
        }
        });
        document.addEventListener('DOMContentLoaded', () => {
        Espo.loader.require('custom:menu', async function (User) {
        const myInstance = new User();
        // const teamID = await myInstance.getUserTeamID();
        const teamID = 'Systems'; // hardcoded for now
        // const teamID = 'sales'; // hardcoded for now
        // const teamID = 'Sales Administration'; // hardcoded for now
        console.log('team :', teamID);
        const configPath = `client/custom/modules/hiden/config/menuTabs/${teamID}.json`;
        const forAllConfig = `client/custom/modules/hiden/config/menuTabs/all.json`;
        try {
        const response = await fetch(configPath);
        const forAllRes = await fetch(forAllConfig);
        if (!response.ok) {
        throw new Error(`Failed to load config for team ${teamID}`);
        }
        tabList = await response.json();
        forAll = await forAllRes.json();
        tabList.unshift(...forAll);
        
        replaceNavTabs(tabList);
        } catch (e) {
        console.error(e);
        }
        });
        });
        function replaceNavTabs(customTabs) {
        function waitForNavTabs(callback, interval = 100, timeout = 5000) {
        const start = Date.now();
        const timer = setInterval(() => {
        const navTabs = document.querySelector('ul.tabs.navbar-nav');
        if (navTabs) {
        clearInterval(timer);
        callback(navTabs);
        } else if (Date.now() - start > timeout) {
        clearInterval(timer);
        console.warn('Nav tabs not found');
        }
        }, interval);
        }
        waitForNavTabs(navTabs => {
        navTabs.innerHTML = '';
        customTabs.forEach(tab => {
        if (tab.type === 'group') {
        // Dropdown group
        const li = document.createElement('li');
        li.className = 'tab tab-group dropdown';
        li.dataset.name = tab.dataName;
        const a = document.createElement('a');
        a.className = 'nav-link-group';
        a.setAttribute('data-toggle', 'dropdown');
        a.href = '#';
        if (tab.shortLabelIcon) {
        const shortSpan = document.createElement('span');
        shortSpan.className = 'short-label';
        shortSpan.innerHTML = `<span class="${tab.shortLabelIcon}" style="color: ${tab.iconColor || 'inherit'}"></span>`;
        a.appendChild(shortSpan);
        }
        if (tab.fullLabel) {
        const fullSpan = document.createElement('span');
        fullSpan.className = 'full-label';
        fullSpan.textContent = tab.fullLabel;
        a.appendChild(fullSpan);
        }
        const caret = document.createElement('span');
        caret.className = 'fas fa-caret-right group-caret';
        a.appendChild(caret);
        li.appendChild(a);
        // Dropdown menu
        const ulDropdown = document.createElement('ul');
        ulDropdown.className = 'dropdown-menu';
        ulDropdown.setAttribute('role', 'menu');
        (tab.items || []).forEach(subTab => {
        const subLi = document.createElement('li');
        subLi.className = 'tab';
        subLi.dataset.name = subTab.dataName;
        const subA = document.createElement('a');
        subA.href = subTab.href || '#';
        subA.className = 'nav-link';
        if (subTab.shortLabelIcon) {
        const shortSpan = document.createElement('span');
        shortSpan.className = 'short-label';
        shortSpan.innerHTML = `<span class="${subTab.shortLabelIcon}" style="color: ${subTab.iconColor || 'inherit'}"></span>`;
        subA.appendChild(shortSpan);
        }
        if (subTab.fullLabel) {
        const fullSpan = document.createElement('span');
        fullSpan.className = 'full-label';
        fullSpan.textContent = subTab.fullLabel;
        subA.appendChild(fullSpan);
        }
        subLi.appendChild(subA);
        ulDropdown.appendChild(subLi);
        });
        li.appendChild(ulDropdown);
        navTabs.appendChild(li);
        } else {
        // Single tab
        const li = document.createElement('li');
        li.className = 'tab';
        li.dataset.name = tab.dataName;
        const a = document.createElement('a');
        a.href = tab.href || '#';
        a.className = 'nav-link';
        if (tab.shortLabelIcon) {
        const shortSpan = document.createElement('span');
        shortSpan.className = 'short-label';
        shortSpan.innerHTML = `<span class="${tab.shortLabelIcon}" style="color: ${tab.iconColor || 'inherit'}"></span>`;
        a.appendChild(shortSpan);
        }
        if (tab.fullLabel) {
        const fullSpan = document.createElement('span');
        fullSpan.className = 'full-label';
        fullSpan.textContent = tab.fullLabel;
        a.appendChild(fullSpan);
        }
        li.appendChild(a);
        navTabs.appendChild(li);
        }
        });
        });
        }
        Last edited by jamie; Today, 02:36 PM. Reason: code

        Comment

        Working...