Announcement

Collapse
No announcement yet.

How to Template Entity in EspoCRM

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

  • telecastg
    commented on 's reply
    Great job theBuzzyCoder !

  • theBuzzyCoder
    commented on 's reply
    I made it into a pluggable extension. You can download it from here: https://github.com/theBuzzyCoder/eSi...ocrm-1.0.0.zip
    Read the readme on how to install the extension and use it.

    It's free!!!!
    Last edited by theBuzzyCoder; 09-20-2019, 10:09 AM.

  • telecastg
    commented on 's reply
    You're welcome. For my application I only wanted esignature fields to be filled once via inline editing but you can override this by commenting the code if(this.mode !== "detail") { this.setMode("detail");} in esignature.js

  • telecastg
    commented on 's reply
    Hi theBuzzyCoder, sorry, no I did not. I am not a professional developer and have been very busy trying to educate myself in Espo to make modifications for my own application.
    Last edited by telecastg; 09-05-2019, 04:42 AM.

  • theBuzzyCoder
    commented on 's reply
    Hi @telecastg,

    Any updates on this. Were you able to make it a pluggable extension? I would really love to see it done!

  • jurnet
    replied
    Thanks a lot , it works.
    If i want to update or to edit but not inline how can i do ?

    Leave a comment:


  • telecastg
    commented on 's reply
    Hi @theBuzzyCoder,

    Good suggestion, I have made some improvements and testing for a practical application, I will check on the link. Thanks.

  • theBuzzyCoder
    commented on 's reply
    Hi telecastg,

    Why don't you create an installable extension for espocrm with same code. The users then will simply add it as plugable module.

    Extensions allow you to add extra functionality to EspoCRM. They can be installed by Administrator panel under Customization section. We will show you how to create the extension package of Project Management (PM) module described in this post Customization: How to create custom entity.

  • telecastg
    commented on 's reply
    Forgot to mention that in order to be able to load the jsignature script when the application loads you have to edit or create custom/Espo/Custom/Resources/metadata/app/client.json and add:

    {
    "scriptList": [
    "__APPEND__",
    "client/custom/lib/jsignature/jSignature.min.noconflict.js"
    ],
    "developerModeScriptList": [
    "__APPEND__",
    "client/custom/lib/jsignature/jSignature.min.noconflict.js"
    ]
    }

  • eymen-elkum
    replied
    Originally posted by peterberlin View Post
    Hello developer,

    we have been looking for a way to capture and save signatures for years.
    If it is possible to integrate this library and save the result in a field of the type picture. These images could then be integrated into a PDF template.
    If this succeeds, ESpo could be used for mobile order entry.
    peter
    I wonder if this is what u mean?

    Leave a comment:


  • telecastg
    replied
    Hello guys,

    I developed a custom "esignature" field to capture electronic signatures, save them to the database and retrieve as images.

    These fields can be created using the Admon UI by selecting "esignature" as type and can only be edited using the inline edit mode.

    1) Download jsignature.min.noconflict.js from http://www.unbolt.net/jSignature/ and save in folder "client/custom/lib/jsignature/"

    2) Copy and save the code files below:

    client/custom/src/views/fields/esignature.js
    Code:
    Espo.define('custom:views/fields/esignature', 'views/fields/base', function (Dep) {
    
        return Dep.extend({
    
            // custom templates
            detailTemplate: 'custom:fields/esignature/detail',
            editTemplate: 'custom:fields/esignature/edit',
            listTemplate: 'custom:fields/esignature/list',
    
            // custom properties
            blankCanvassCode: '',
    
            // custom methods        
            init: function () { // overrides "init" function from base.js
                if (this.events) {
                    this.events = _.clone(this.events);
                } else {
                    this.events = {};
                }
                this.defs = this.options.defs || {};
                this.name = this.options.name || this.defs.name;
                this.params = this.options.params || this.defs.params || {};
                this.fieldType = this.model.getFieldParam(this.name, 'type') || this.type;
                this.getFieldManager().getParamList(this.type).forEach(function (d) {
                    var name = d.name;
                    if (!(name in this.params)) {
                        this.params[name] = this.model.getFieldParam(this.name, name);
                        if (typeof this.params[name] === 'undefined') {
                            this.params[name] = null;
                        }
                    }
                }, this);
                var additionaParamList = ['inlineEditDisabled'];
                additionaParamList.forEach(function (item) {
                    this.params[item] = this.model.getFieldParam(this.name, item) || null;
                }, this);
                this.mode = this.options.mode || this.mode;
                this.tooltip = this.options.tooltip || this.params.tooltip || this.model.getFieldParam(this.name, 'tooltip');
                this.disabledLocked = this.options.disabledLocked || false;
                this.disabled = this.disabledLocked || this.options.disabled || this.disabled;
                // signature fields can only be seen in detail mode
                this.setMode('detail');
                this.on('invalid', function () {
                    var $cell = this.getCellElement();
                    $cell.addClass('has-error');
                    this.$el.one('click', function () {
                        $cell.removeClass('has-error');
                    });
                    this.once('render', function () {
                        $cell.removeClass('has-error');
                    });
                }, this);
                if ((this.isDetailMode() || this.isEditMode()) && this.tooltip) {
                    this.initTooltip();
                }
                // signature fields can only be edited inline
                this.listenToOnce(this, 'after:render', this.initInlineEsignatureEdit, this);            
                this.attributeList = this.getAttributeList();
                this.listenTo(this.model, 'change', function (model, options) {
                    if (this.isRendered() || this.isBeingRendered()) {
                        if (options.ui) {
                            return;
                        }
                        var changed = false;
                        this.attributeList.forEach(function (attribute) {
                            if (model.hasChanged(attribute)) {
                                changed = true;
                            }
                        });
                        if (changed) {
                            this.reRender();
                        }
                    }
                }.bind(this));
                this.listenTo(this, 'change', function () {
                    var attributes = this.fetch();
                    this.model.set(attributes, {ui: true});
                });
            },
    
            data: function () { // overrides "data" function from base.js
                var imageSource = this.getValueForDisplay();
                var data = {
                    scope: this.model.name,
                    name: this.name,
                    defs: this.defs,
                    params: this.params,
                    value: this.getValueForDisplay(),
                    imageSource: imageSource                
                };  
                // signature fields can not be edited manually, force detail mode
                if(this.mode !== "detail") {
                    this.setMode("detail");
                }
                return data;
            },
    
            initInlineEsignatureEdit: function () { // custom function equivalent to "initInlineEdit" at base.js  
                var $cell = this.getCellElement();
                var $editLink = $('<a href="javascript:" class="pull-right inline-edit-link hidden"><span class="fas fa-pencil-alt fa-sm"></span></a>');
                if ($cell.length === 0 || typeof(this.model.get(this.name))=== 'undefined') {
                    this.listenToOnce(this, 'after:render', this.initInlineEsignatureEdit, this);
                    return;
                }
                // if the signature field already has a value do not add the inline edit link and set the field as readonly
                if(this.model.get(this.name)) {
                    this.readOnly = true;
                    return;                
                }
                // after the element has been rendered, add the hidden pencil icon link
                $cell.prepend($editLink);
                $editLink.on('click', function () {
                    // when clicked, call the custom signature field inline edit function
                    this.inlineEsignatureEdit();
                // bind the functionality to the pencil icon link    
                }.bind(this));
                $cell.on('mouseenter', function (e) {
                    e.stopPropagation();
                    if (this.disabled || this.readOnly) {
                            return;
                    }
                    if (this.mode === 'detail') {
                        $editLink.removeClass('hidden');
                    }
                }.bind(this)).on('mouseleave', function (e) {
                    e.stopPropagation();
                    if (this.mode === 'detail') {
                        $editLink.addClass('hidden');
                    }
                }.bind(this));
            },
    
            inlineEsignatureEdit: function() { // custom function equivalent to "inlineEdit" at base.js            
                // add css class esignature to the field element
                this.$el.addClass('eSignature');
                // initialize jSignature plug-in to display canvas input
                var $sigDiv = this.$el.jSignature({'UndoButton':true, 'color':'rgb(5, 1, 135)'});
                this.blankCanvassCode = this.$el.jSignature('getData', 'image');
                // add the inline action links ("Update" and "Cancel")
                this.addInlineEditLinks(); // function inherited from base.js              
            },
    
            inlineEditClose: function () { // substitutes same function at base.js
                this.trigger('inline-edit-off');
                this._isInlineEditMode = false;
                this.once('after:render', function () {
                    // remove the inline edit links
                    this.removeInlineEditLinks(); // function inherited from base.js
                }, this);
                // re-renders the entity in detail mode
                this.reRender(true);
            },
    
            inlineEditSave: function () { // substitutes same function at base.js  
                // convert the canvas drawing to image code
                var imageCode = this.$el.jSignature('getData', 'image');
                // compare the contents of the current vs blank canvass to make sure there's a signature to be saved
                if(this.blankCanvassCode[1] === imageCode[1]) {
                    alert("No signature was entered");
                    this.inlineEditClose();
                    return;
                }            
                // prepare the signature drawing to be stored in the database
                var imageSource = 'data:'+this.$el.jSignature('getData', 'image');
                this.notify('Saving...');
                var self = this;
                var model = this.model;
                var prev = this.initialAttributes;
                var data = model.attributes;
                // store the image code as the field value
                data[this.name] = imageSource;
                // persist the model with the updated field value
                this.model.save(data, {
                    success: function () {
                        self.trigger('after:save');
                        model.trigger('after:save');
                        self.notify('Saved', 'success');
                    },
                    error: function () {
                        self.notify('Error occured', 'error');
                        // undo all field value changes
                        model.set(prev, {silent: true});
                        // re-render with the original values
                        self.render();
                    },
                    patch: true
                });
                this.inlineEditClose();
            }
    
        });
    });
    custom/Espo/Custom/Resources/metadata/fields/esignature.json
    Code:
    {
       "params":[
       ],
       "notCreatable": false,
       "filter": false,
       "fieldDefs":{
          "type":"text",
          "notStorable":false  
       },
       "view": "custom:views/fields/esignature",
       "textFilter": false,
       "filter": false,
       "fullTextSearch": false,    
       "readOnly": false
    }
    client/custom/res/templates/fields/esignature/detail.tpl
    Code:
    {{#if value}}
        <img src='{{{imageSource}}}' />
    {{else}}  
    {{/if}}
    client/custom/res/templates/fields/esignature/edit.tpl
    Code:
    {{#if value}}
        <img src='{{imageSource}}' />
    {{else}}
        {{translate 'None'}}
    {{/if}}
    client/custom/res/templates/fields/esignature/list.tpl
    Code:
    {{#if value}}
        <img src='{{imageSource}}' />
    {{else}}
        {{translate 'None'}}
    {{/if}}
    Saludos
    Last edited by telecastg; 04-28-2019, 02:02 AM.

    Leave a comment:


  • pmontanez
    replied
    Hey Guys,

    I'll love to see this implemented too - But I understand that developers had thousand of system-wide priorities - Maybe crowdfunding can get this and other important addition to system possible -
    Anybody else interested?

    Leave a comment:


  • peterberlin
    replied
    Hello developer,

    we have been looking for a way to capture and save signatures for years.
    If it is possible to integrate this library and save the result in a field of the type picture. These images could then be integrated into a PDF template.
    If this succeeds, ESpo could be used for mobile order entry.
    peter

    Leave a comment:


  • theBuzzyCoder
    started a topic How to Template Entity in EspoCRM

    How to Template Entity in EspoCRM

    Hi,

    I am trying to generate a PDF Template using Template. But I don't know a thing about it. Is there a documentation for it?

    I want to generate a PDF where user of the PDF can add his/her signature like a input box to sign in the PDF. Is there way to achieve it.

    For example:
Working...
X