Announcement

Collapse
No announcement yet.

Coding Tutorial: How to create a custom navbar menu item

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • Coding Tutorial: How to create a custom navbar menu item

    This tutorial explains the steps needed to create a custom navbar menu item ("CustomMenu") and the controller that will execute the functions desired when a user clicks on that menu item.

    Step 1
    Create a scope definition file.
    custom/Espo/Custom/Resources/metadata/scopes/CustomMenu.json
    Code:
    {
        "entity": false,
        "tab": true,
        "acl": "true",
        "aclPortal": true,
        "aclPortalLevelList": [
            "all",
            "account",
            "contact",
            "own",
            "no"
        ],
        "disabled": false,
        "module": "Custom",
        "isCustom": true
    }
    Notice that the setting "entity" is set to false so Espo will not create a table or expect to find an entityDefs json script or create a database table "custom-menu", also notice that the setting "tab" is set to true, so the menu item will be available to add from Administration > User Interface panel.

    Step 2
    Create a clientDefs metadata file, to tell Expo which front end controller will contain the instructions to execute when a User clicks on the custom menu item.
    custom/Espo/Custom/Resources/metadata/clientDefs/CustomMenu.json
    Code:
    {
        "controller": "custom:controllers/custom-menu",
        "color": "#00ff66",
        "iconClass": "fas fa-file-contract"
    }
    Step 3
    Create the front-end controller that will execute actions when a User clicks on the custom menu item
    client/custom/src/controllers/custom-menu.js
    Code:
    define('custom:controllers/custom-menu', 'controllers/base', function (Dep) {
    
        return Dep.extend({
    
            // default action
            actionIndex: function (options) {
                alert("This Custom Menu is working fine !");
            }
    
        });
    });
    Step 4
    Create a language json script to make the custom scope label "human friendly" in your preferred language
    custom/Espo/Custom/Resources/i18n/en_US/Global.json
    Code:
    {
        "scopeNames": {
            "CustomMenu": "Custom Menu"
        },
        "scopeNamesPlural": {
            "CustomMenu": "Custom Menu"
        }
    }
    Step 5
    Clear cache and rebuild
    Administration > Rebuild

    Step 6
    Add the new menu item to the side navbar
    Administration > User Interface > Tab List (click "Add", select "Custom Menu" from the tab list options, position where you want it to appear, and click "Save")

    Step 7
    Reload the page
    Last edited by telecastg; 02-18-2021, 06:49 AM.

  • #2
    Hello telecastg ,
    Thanks

    juste two question :
    - have you a print-screen for what do this code ?
    - do you think it's possible have custom menu depedant of User ? (teams maybe but one User can be in many Teams .. so i imagine it's complicate )

    Regards

    Comment


    • #3
      Hi telecastg
      thanks you,
      but it still doesn't work, I will have to create a new instance or update the crm (my actually version 6.0.3).
      I followed all the steps correctly (copy and paste) and I apologize it is the first time with crm and thanks for the help and for the patience.


      Comment


      • Tuki
        Tuki commented
        Editing a comment
        in the console nothing and in a log alone this

        this is from yesterday :c :c and thanks for you time teacher
        [2021-02-15] Espo.ERROR: (409) Link [Opportunity:riginalLead] already exists.; POST /EntityManager/action/createLink; line: 721, file: /home/xxx/public_html/xxx/application/Espo/Tools/EntityManager/EntityManager.php [] []

      • telecastg
        telecastg commented
        Editing a comment
        [2021-02-15] Espo.ERROR: (409) Link [Opportunity:OriginalLead] already exists.; POST /EntityManager/action/createLink; line: 721, file: /home/xxx/public_html/xxx/application/Espo/Tools/EntityManager/EntityManager.php [] []

        This error has nothing to do with the code that I posted. The tutorial above doesn't do anything in the back-end so it wouldn't throw any PHP errors.

        The error message above is telling you that you are trying to create a link that already exists.... not sure why or where it may be originating from. Looks like it is part of some customization in the entity manager.

        If you are just starting I suggest to install a fresh image without any customizations and test the code that I posted.
        Last edited by telecastg; 02-16-2021, 10:07 PM.

      • Tuki
        Tuki commented
        Editing a comment
        I am working with a new instance, thank you for you help.

        it works...

    • #4
      Hello item .

      Question 1: What can be done with the custom menu item controller ?

      This code is a very simplified example to teach how to create a custom button and have it do something, not part of any real code.

      In this case all this code does is to display an "alert" window saying "This Custom Menu is working fine".

      For a real implementation you would need to write code under the function "actionIndex" in the controller (client/custom/src/controllers/custom-menu.js) to do something else.

      For example:

      To retrieve an object containing list of "Lead" records, you would write an Ajax call (actually an API call) to the "Lead" back-end controller like this:
      Code:
              actionIndex: function (options) {
                  $.ajax({
                      type: 'GET',
                      url: 'Lead/action/list',
                      error: function () {
                          console.log('error attempting to retrieve a list of Leads');
                      }.bind(this)
                      }).done(function(response){
                          // in this example "response" will be an array of Lead entities, and for each entity the fields retrieved would be the same as the fields specified in the "list" layout
                          console.log("response: ",response);
                  }.bind(this));
              }
      To redirect Espo to display a list of Leads the code would be as follows:
      Code:
              actionIndex: function (options) {
                  var url = '#Lead/list/';
                  // invoke the controller to render the record selected
                  this.getRouter().dispatch('Lead', 'list');
                  // navigate to the list view and add url to the browsing history
                  this.getRouter().navigate(url);
              }
      As you can see, the possibilities of what you can do with the custom controller are endless, you can write javascript code to execute front-end actions or call a back-end controller to execute back-end actions.

      Question 2: Can the actions of the custom menu item controller be dependent on a User's role ?

      Yes you can specify actions by a single User but you would have to know the User record ID which is kind of an overkill because you would have to re-write your software each time a User is added or deleted.

      A better solution, in my opinion would be to use "Role" in which you can add or drop Users anytime without having to re-code anything.

      For example, to display a list of Leads only if the current User has the role of "Important Sales Manager", your code would look like this:
      Code:
              actionIndex: function (options) {
                  var url = 'User/'+this.getUser().id+'/roles';
                  var roleFilter = "Important Sales Manager";
                  $.ajax({
                      type: 'GET',
                      url: url,
                      error: function () {
                          console.log('error attempting to retrieve a list of Roles for the current User id = ', this.getUser().id);
                      }.bind(this)
                  }).done(function(response){
                      // console.log("User roles = ",response); // un-comment this line if you want to see the response object in your browser's console
                      // proceed only if the User has the role specified in "roleFilter"
                      if(response.list.find(x => x.name === roleFilter).id) {
                          this.getRouter().dispatch('Lead', 'list');
                          this.getRouter().navigate('#Lead/list/');
                      }    
                  }.bind(this));
              }
      Best Regards
      Last edited by telecastg; 02-16-2021, 07:14 PM.

      Comment


      • telecastg
        telecastg commented
        Editing a comment
        You're welcome item :-) sorry not time for live help, our own development keeps me quite busy and sometimes (like many coders I assume) I work odd hours :-)

        One question about the forum for you, how do you insert emojis in comments ?

      • item
        item commented
        Editing a comment
        Ahh always no time .. this is our life

        emoti .. bah simple i use sample :

        : D =>
        : ) =>

        Remove space between : and ) for sample
        Last edited by item; 02-16-2021, 10:33 PM.

      • telecastg
        telecastg commented
        Editing a comment
        Thanks !

    • #5
      For some reason, when I had "acl": "true" or "acl":true, the tab was not visible for global administrator and therefore could not be added under Administration->User Interface. After some digging, I decided to view my user account and clicked the "Access" button to see what access I had. Interestingly, it did not give me access to the custom menu item (it was still set to denied) and that is why I could not add it in Administration -> User Interface.

      I could not figure out how to grant access to it (like with a normal User) because the global administrator doesn't have a 'role' setup by default on ESPOCRM install. When creating entities and such as an admin in the GUI, it seems to always grant access upon creation which is what I would have expected here as well.

      I was able to give the admin user access to the custom menu item by defining it this way "acl": "boolean". I really don't understand what that value-setting is for, but it works. According to the link below, "acl", is a boolean type or the string "boolean". Maybe this only applies if the user using the GUI is a global administrator with no role setup? Here is the code that worked:

      custom/Espo/Custom/Resources/metadata/scopes/CustomMenu.json

      Code:
      {
           "entity": false,
           "tab": true,
           "acl": "boolean",
           "aclPortal": true,
           "aclActionList": ["read", "edit"],
           "aclActionLevelListMap": {
           "edit": ["own", "no"]
      },
           "aclPortalLevelList": [
                "account",
                "own",
                "no"
           ],
           "disabled": false,
           "module": "Custom",
           "isCustom": true,
           "customizable": false,
           "object": true
      }​

      Comment


      • Paulina
        Paulina commented
        Editing a comment
        Thanks for your suggestion, I had the same problem too.

    • #6
      All, Kia ora from New Zealand. I have followed the instructions above, and I do not get a "Custom Menu" choice to add under "Administration -> User Interface".

      I did notice that I did not have the directory as per Step 3 (client/custom/src/controllers/) on my server, so I created it and set the ownership & perms as per standard.

      I have also tried both "json" settings as per Step 1 and as per czcpf, and after "rebuild" still no ability to add to navbar.

      Also nothing is added to espo-log.

      TIA,
      David.

      Comment


      • #7
        I had the same problem too.

        Comment


        • #8
          abidoss Try changing the user language setting (Preferences) to "English (US)"

          Comment

          Working...
          X