Announcement

Collapse
No announcement yet.

Created Custom Entity called "Own employed" and like connect for portalUser Creation

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

  • Created Custom Entity called "Own employed" and like connect for portalUser Creation

    Dear Team,
    Please don't reprimand me, I posted this question in the German-speaking area first, but I think I might get more response here.

    I created a custom entity called like "own-employed" (in german: "Eigene Mitarbeiter - eigeneMitarbeiter") as Person with the Person Template.

    After that we filled the employee data. Then we created a portal for the employees and started to create portal users.

    At this point we realized that only the people who are listed in contacts are displayed when creating a portal user.

    So we started and tried to connect them with relations. But there was no success yet.

    We also tried some .json example coding but without any effect.

    We also have read these:
    Hi, i wanna ask something related to entity management and user portal. So.. my custom entity is not shown on the user portal management, can I add my custom


    Please help solve an important problem using the Workflow or other formula. Condition: The client first registers on the third-party Terminal service and is assigned terminalAccountID (int) there. Then this value is passed to ESPOCRM in the terminalAccountID (integer) field of the "Contact", with all other data for


    I'm evaluating the best way to support job applicants in EspoCRM using portals / portal users. Is it correct that portal users are bound to Contacts? Since


    Note: It's possible to create custom entity through Admin UI. This article is outdated. I'm going to show you how to create new entities in EspoCRM manually. We will make new simple module called PM (Project Management) with Projects and Tasks entities.


    Maybe something simple is missing that I do not see right now.

    We will be happy, if you have a solution for this case. I am also good in PHP and WebCoding. So any programming advice should be easily realized.
    Thank you for your time.

  • #2
    Hi,

    You can create a custom portal-user list view, just clone this view https://github.com/espocrm/espocrm/b...l-user/list.js and change it with your entity.
    also this https://github.com/espocrm/espocrm/b...portal-user.js

    then in your custom folder define a custom list view for PortalUser.json https://github.com/espocrm/espocrm/b...ortalUser.json

    I think that it could work like this, needs more investigation.

    Comment


    • #3
      Thanks for the quick response. We will try and let you know if we succeeded.

      Comment


      • #4
        Let me know if you need any help!

        Comment


        • #5
          Welcome Mr Coder! Always good to have people with these skill set. This thread might be relevant for you to create Custom Portal:

          Custom Portal Setup (multiple-portal) - https://forum.espocrm.com/forum/gene...up-help-apache

          Taken from: https://github.com/o-data/EspoCRM-Le...nd-Design/wiki

          Comment


          • #6
            Hi. I tried what you explained in the first place with the .js files. The only result is that I see this error message: 404 not found

            You suggested cloning, but because we want to display only the "EigeneMitarbeiter" instead of the normal Contact List I changed the code.

            I am also curious about the double defining or overwrting the variable "viewName";

            I think these lines are a development thing and in fact we only need the second line.


            var viewName = this.getMetadata().get('clientDefs.EigeneMitarbeit er.modalViews.select') || 'views/modals/select-records';

            var viewName = 'crm:views/eigenemitarbeiter/modals/select-for-portal-user';​



            So Everywhere there was Contact or contact I changed to EigeneMitarbeiter and eigeneMitarbeiter. Please be beware of the little and big characters in writing here.

            This is the Code for list.js:

            define('views/portal-user/list', 'views/list', function (Dep) {

            return Dep.extend({

            defaultOrderBy: 'createdAt',

            defaultOrder: 'desc',

            setup: function () {
            Dep.prototype.setup.call(this);
            },

            actionCreate: function () {
            var viewName = this.getMetadata().get('clientDefs.EigeneMitarbeit er.modalViews.select') || 'views/modals/select-records';

            var viewName = 'crm:views/eigenemitarbeiter/modals/select-for-portal-user';

            this.createView('modal', viewName, {
            scope: 'EigeneMitarbeiter',
            primaryFilterName: 'notPortalUsers',
            createButton: false,
            mandatorySelectAttributeList: [
            'salutationName',
            'firstName',
            'lastName',
            'accountName',
            'accountId',
            'emailAddress',
            'emailAddressData',
            'phoneNumber',
            'phoneNumberData'
            ]
            }, function (view) {
            view.render();

            this.listenToOnce(view, 'select', function (model) {
            var attributes = {};

            attributes.contactId = model.id;
            attributes.contactName = model.get('name');

            if (model.get('accountId')) {
            var names = {};
            names[model.get('accountId')] = model.get('accountName');

            attributes.accountsIds = [model.get('accountId')];
            attributes.accountsNames = names;
            }

            attributes.firstName = model.get('firstName');
            attributes.lastName = model.get('lastName');
            attributes.salutationName = model.get('salutationName');

            attributes.emailAddress = model.get('emailAddress');
            attributes.emailAddressData = model.get('emailAddressData');

            attributes.phoneNumber = model.get('phoneNumber');
            attributes.phoneNumberData = model.get('phoneNumberData');

            attributes.userName = attributes.emailAddress;

            attributes.type = 'portal';

            var router = this.getRouter();

            var url = '#' + this.scope + '/create';

            router.dispatch(this.scope, 'create', {
            attributes: attributes
            });
            router.navigate(url, {trigger: false});
            }, this);

            this.listenToOnce(view, 'skip', function (model) {
            var attributes = {
            type: 'portal'
            };

            var router = this.getRouter();
            var url = '#' + this.scope + '/create';
            router.dispatch(this.scope, 'create', {
            attributes: attributes
            });
            router.navigate(url, {trigger: false});
            }, this);
            }, this);
            }

            });
            });​

            The other file I changed the path like that:

            define('crm:views/eigenemitarbeiter/modals/select-for-portal-user', ['views/modals/select-records'], function (Dep) {

            return Dep.extend({

            setup: function () {
            Dep.prototype.setup.call(this);

            this.buttonList.unshift({
            name: 'skip',
            text: this.translate('Weiter mit Mitarbeiter', 'labels', 'User')
            });
            },

            actionSkip: function () {
            this.trigger('skip');
            this.remove();
            },
            });
            });​

            But I only get error "404 not found". What does this error mean? Is it possible that this error occurs because of missing values like:
            'salutationName',
            'firstName',
            'lastName',
            'accountName',
            'accountId',
            'emailAddress',
            'emailAddressData',
            'phoneNumber',
            'phoneNumberData'​ etc. so in the Peron Template we used there are none of these fields called like that.
            So if this is the problem, we can delete the entity an make a new one with the right fields.

            We are looking forward your answer. Thank you very much.
            Attached Files

            Comment


            • #7
              I think it's because the view you defined doesn't exist.

              crm:views/eigenemitarbeiter/modals/select-for-portal-user'

              That's why it would have been better to recreate them and then ovverride in the json.

              Read about custom views in the docs please https://docs.espocrm.com/development/custom-views/

              If I have the time I'll try to make a proof of concept on how to do it if you can't make it work.

              Comment


              • #8
                Okay. There have been more questions. You only answered one. This would be better to help me understand how this works.

                I also created this file here: client/modules/crm/src/views/eigenedateien/modals/select-for-portal-user.js

                an the other files ....

                Click image for larger version

Name:	grafik.png
Views:	473
Size:	9.2 KB
ID:	89092



                Your first advice was this just clone etc.

                so the list.js looks now like this

                Code:
                
                define('views/portal-user/list', 'views/list', function (Dep) {
                
                    return Dep.extend({
                
                        defaultOrderBy: 'createdAt',
                
                        defaultOrder: 'desc',
                
                        setup: function () {
                            Dep.prototype.setup.call(this);
                        },
                
                        actionCreate: function () {
                            var viewName = this.getMetadata().get('clientDefs.Contact.modalViews.select') || 'views/modals/select-records';
                
                            var viewName = 'crm:views/contact/modals/select-for-portal-user';
                
                            this.createView('modal', viewName, {
                                scope: 'Contact',
                                primaryFilterName: 'notPortalUsers',
                                createButton: false,
                                mandatorySelectAttributeList: [
                                    'salutationName',
                                    'firstName',
                                    'lastName',
                                    'accountName',
                                    'accountId',
                                    'emailAddress',
                                    'emailAddressData',
                                    'phoneNumber',
                                    'phoneNumberData'
                                ]
                            }, function (view) {
                                view.render();
                
                                this.listenToOnce(view, 'select', function (model) {
                                    var attributes = {};
                
                                    attributes.contactId = model.id;
                                    attributes.contactName = model.get('name');
                
                                    if (model.get('accountId')) {
                                        var names = {};
                                        names[model.get('accountId')] = model.get('accountName');
                
                                        attributes.accountsIds = [model.get('accountId')];
                                        attributes.accountsNames = names;
                                    }
                
                                    attributes.firstName = model.get('firstName');
                                    attributes.lastName = model.get('lastName');
                                    attributes.salutationName = model.get('salutationName');
                
                                    attributes.emailAddress = model.get('emailAddress');
                                    attributes.emailAddressData = model.get('emailAddressData');
                
                                    attributes.phoneNumber = model.get('phoneNumber');
                                    attributes.phoneNumberData = model.get('phoneNumberData');
                
                                    attributes.userName = attributes.emailAddress;
                
                                    attributes.type = 'portal';
                
                                    var router = this.getRouter();
                
                                    var url = '#' + this.scope + '/create';
                
                                    router.dispatch(this.scope, 'create', {
                                        attributes: attributes
                                    });
                                    router.navigate(url, {trigger: false});
                                }, this);
                
                                this.listenToOnce(view, 'skip', function (model) {
                                    var attributes = {
                                        type: 'portal'
                                    };
                
                                    var router = this.getRouter();
                                    var url = '#' + this.scope + '/create';
                                    router.dispatch(this.scope, 'create', {
                                        attributes: attributes
                                    });
                                    router.navigate(url, {trigger: false});
                                }, this);
                            }, this);
                        }
                
                    });
                });
                
                
                define('views/portal-user/list', 'views/list', function (Dep) {
                
                    return Dep.extend({
                
                        defaultOrderBy: 'createdAt',
                
                        defaultOrder: 'desc',
                
                        setup: function () {
                            Dep.prototype.setup.call(this);
                        },
                
                        actionCreate: function () {
                            var viewName = this.getMetadata().get('clientDefs.EigeneMitarbeiter.modalViews.select') || 'views/modals/select-records';
                
                            var viewName = 'crm:views/eigenemitarbeiter/modals/select-for-portal-user';
                
                            this.createView('modal', viewName, {
                                scope: 'EigeneMitarbeiter',
                                primaryFilterName: 'notPortalUsers',
                                createButton: false,
                                mandatorySelectAttributeList: [
                                    'salutationName',
                                    'firstName',
                                    'lastName',
                                    'accountName',
                                    'accountId',
                                    'emailAddress',
                                    'emailAddressData',
                                    'phoneNumber',
                                    'phoneNumberData'
                                ]
                            }, function (view) {
                                view.render();
                
                                this.listenToOnce(view, 'select', function (model) {
                                    var attributes = {};
                
                                    attributes.contactId = model.id;
                                    attributes.contactName = model.get('name');
                
                                    if (model.get('accountId')) {
                                        var names = {};
                                        names[model.get('accountId')] = model.get('accountName');
                
                                        attributes.accountsIds = [model.get('accountId')];
                                        attributes.accountsNames = names;
                                    }
                
                                    attributes.firstName = model.get('firstName');
                                    attributes.lastName = model.get('lastName');
                                    attributes.salutationName = model.get('salutationName');
                
                                    attributes.emailAddress = model.get('emailAddress');
                                    attributes.emailAddressData = model.get('emailAddressData');
                
                                    attributes.phoneNumber = model.get('phoneNumber');
                                    attributes.phoneNumberData = model.get('phoneNumberData');
                
                                    attributes.userName = attributes.emailAddress;
                
                                    attributes.type = 'portal';
                
                                    var router = this.getRouter();
                
                                    var url = '#' + this.scope + '/create';
                
                                    router.dispatch(this.scope, 'create', {
                                        attributes: attributes
                                    });
                                    router.navigate(url, {trigger: false});
                                }, this);
                
                                this.listenToOnce(view, 'skip', function (model) {
                                    var attributes = {
                                        type: 'portal'
                                    };
                
                                    var router = this.getRouter();
                                    var url = '#' + this.scope + '/create';
                                    router.dispatch(this.scope, 'create', {
                                        attributes: attributes
                                    });
                                    router.navigate(url, {trigger: false});
                                }, this);
                            }, this);
                        }
                
                    });
                });
                
                
                ​
                Last edited by biocronic; 03-09-2023, 12:29 PM.

                Comment


                • rabii
                  rabii commented
                  Editing a comment
                  I think you should create these files under custom\Espo\Custom otherwise it won't be upgrade safe.

                  define('views/portal-user/list', 'views/list', function (Dep) => This is wrong as it is an existing file in the system it should something like define('views/eigenemitarbeiter-user/list', 'views/list', function (Dep)

                  remember you need first to create a relationship between users and your custom entity and then start creating necessary views and implement logic. Also keep in mind that you have to implement you own custom code for Portal Roles and Permissions.

              • #9
                Hi. Just another little question for more clearness:
                I assume that I should replace CRM with CUSTOM in the php define code:
                define('crm:views/ change to define('custom:views/ ?
                Is this right?

                Comment


                • #10
                  Another question you missed perhaps.....

                  var viewName = this.getMetadata().get('clientDefs.Contact.modalVi ews.select') || 'views/modals/select-records';

                  var viewName = 'crm:views/contact/modals/select-for-portal-user';​

                  the first line is not necessary? RIGHT?

                  Comment


                  • rabii
                    rabii commented
                    Editing a comment
                    No hence you want to create portal users from a different entity other than Contact then it should reflect the clientDefs of your custom entity.

                • #11
                  Hello Ladies and Gentlemen!

                  Somehow I destroyed my entity, so I created an new one and read the documentation and your advices again and again.
                  This is where I ended now. Now I do not have any error messages but did not achieve yet what I wanted to.
                  I want to explain it in detail again because I think some things might be unclear.

                  First I explain what I want to achieve:
                  On the Admin-Page: Portal Users
                  URL: .../espocrm/#Admin/portalUsers

                  There is an Add Portal User Button.
                  Click image for larger version

Name:	grafik.png
Views:	305
Size:	10.2 KB
ID:	89569
                  After clicking ... opening....

                  Click image for larger version

Name:	grafik.png
Views:	313
Size:	13.1 KB
ID:	89570

                  Here we see the Contacts Entity loaded. Instead of this Contact list, I like to load my new Entity "Angestellte".

                  Click image for larger version

Name:	grafik.png
Views:	301
Size:	6.8 KB
ID:	89571
                  Our Contacts exist als a child of Customers (Kunden), so we do not want display the Contacts when adding the Portal Users. so instead: Angestellte.



                  Now I tell you what I have done so far:

                  I created a new entity named "angestellte" as person linked to USERS from the admin backend.

                  so the Clientdef here was created automaticly: /espocrm/custom/Espo/Custom/Resources/metadata/clientDefs/Angestellte,json

                  Kharg ... Then you told me to clone these two first:

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

                  and the same with this one




                  Documentation told me to put it here:

                  client/custom/src/views/angestellte/list.js
                  client/custom/src/views/angestellte/modals/select-for-portal-users.js

                  define('custom:views/angestellte/list', 'views/list', function (Dep) {

                  return Dep.extend({

                  defaultOrderBy: 'createdAt',

                  defaultOrder: 'desc',

                  setup: function () {
                  Dep.prototype.setup.call(this);
                  },

                  actionCreate: function () {
                  var viewName = this.getMetadata().get('clientDefs.Angestellte.mod alViews.select') || 'views/modals/select-records';

                  var viewName = 'custom:views/angestellte/modals/select-for-portal-user';

                  this.createView('modal', viewName, {
                  scope: 'Angestellte',
                  primaryFilterName: 'notPortalUsers',
                  createButton: false,
                  mandatorySelectAttributeList: [
                  'salutationName',
                  'firstName',
                  'lastName',
                  'accountName',
                  'accountId',
                  'emailAddress',
                  'emailAddressData',
                  'phoneNumber',
                  'phoneNumberData'
                  ]
                  }, function (view) {
                  view.render();

                  this.listenToOnce(view, 'select', function (model) {
                  var attributes = {};

                  attributes.contactId = model.id;
                  attributes.contactName = model.get('name');

                  if (model.get('accountId')) {
                  var names = {};
                  names[model.get('accountId')] = model.get('accountName');

                  attributes.accountsIds = [model.get('accountId')];
                  attributes.accountsNames = names;
                  }

                  attributes.firstName = model.get('firstName');
                  attributes.lastName = model.get('lastName');
                  attributes.salutationName = model.get('salutationName');

                  attributes.emailAddress = model.get('emailAddress');
                  attributes.emailAddressData = model.get('emailAddressData');

                  attributes.phoneNumber = model.get('phoneNumber');
                  attributes.phoneNumberData = model.get('phoneNumberData');

                  attributes.userName = attributes.emailAddress;

                  attributes.type = 'portal';

                  var router = this.getRouter();

                  var url = '#' + this.scope + '/create';

                  router.dispatch(this.scope, 'create', {
                  attributes: attributes
                  });
                  router.navigate(url, {trigger: false});
                  }, this);

                  this.listenToOnce(view, 'skip', function (model) {
                  var attributes = {
                  type: 'portal'
                  };

                  var router = this.getRouter();
                  var url = '#' + this.scope + '/create';
                  router.dispatch(this.scope, 'create', {
                  attributes: attributes
                  });
                  router.navigate(url, {trigger: false});
                  }, this);
                  }, this);
                  }

                  });
                  });​


                  // select-for-portal-users.js

                  define('custom:views/angestellte/modals/select-for-portal-user', ['views/modals/select-records'], function (Dep) {

                  return Dep.extend({

                  setup: function () {
                  Dep.prototype.setup.call(this);

                  this.buttonList.unshift({
                  name: 'skip',
                  text: this.translate('Proceed w/o Angestellte', 'labels', 'User')
                  });
                  },

                  actionSkip: function () {
                  this.trigger('skip');
                  this.remove();
                  },
                  });
                  });​

                  So I finally did everything I found in the documentation and your adviced.

                  But now there is NO RESULT. EVEN NO ERROR.

                  So please give me some advice. This should be a easy task for your company so solve within your support. I only want to change the selection of Contact TO Angestellte when adding portal users as admin in the backend.

                  I tried my very best to tell you exactly what is going on. But If you have more questions to investigate let me know.

                  Thank you for your reading in the first place.
                  Attached Files

                  Comment


                  • #12
                    Hi,

                    Did you define your custom views in PortalUser.json?

                    Create a new file in custom/Espo/Custom/Resources/metadata/clientDefs/ called PortalUser.json
                    with the following content
                    PHP Code:
                    {
                        
                    "views": {
                            
                    "list""custom:views/angestellte/list"
                        
                    }
                    }
                    ​ 
                    Rebuild and check if it works.

                    Be aware that you should remove this line: primaryFilterName: 'notPortalUsers', from your custom view as you didn't create a filter for it yet.
                    Last edited by Kharg; 03-17-2023, 03:45 PM.

                    Comment


                    • #13
                      Hi. I did like you told me. Now I have Error 404: Not found again.

                      Made file with this content: PortalUser.json
                      PHP Code:
                      {
                          
                      "views": {
                              
                      "list""custom:views/angestellte/list"
                          
                      }
                      }
                      ​  ​ 
                      removed this line: : primaryFilterName: 'notPortalUsers', .... in list view.

                      I am looking forward your solution. Thank you very much.

                      Comment


                      • #14
                        Can you check the browser console to see what's the error?

                        It should tell you the path of the missing view.
                        Last edited by Kharg; 03-17-2023, 05:57 PM.

                        Comment


                        • biocronic
                          biocronic commented
                          Editing a comment
                          Thank you very much! That very helpful.

                      • #15
                        biocronic tested and working.

                        Just a few things, you need a custom filter so it doesn't show Users already created and you need to make it link the correct entity in the portal user page, as it tries to link the contact entity.
                        Click image for larger version  Name:	image.png Views:	0 Size:	13.9 KB ID:	89603
                        Click image for larger version  Name:	image.png Views:	0 Size:	41.4 KB ID:	89602

                        Edit: Version 1.1.0 has filters and links the correct Angestellte, be aware that your entity has to be names "Angestellte" with a capital "A".​ (if you have already built relationships it may conflict so download 1.0.0 and build a version that works for you by checking the differences)

                        Both versions have to be installed from the extensions panel.
                        Attached Files
                        Last edited by Kharg; 03-17-2023, 11:51 PM.

                        Comment


                        • biocronic
                          biocronic commented
                          Editing a comment
                          Thank you very much. Your help is awesome. I will try it and let you know.

                        • Kharg
                          Kharg commented
                          Editing a comment
                          Let me know if it works!
                      Working...
                      X