sort comment log with latest first

I need to sort my comment log by latest first.

I can do this in the showCommentLog method of the field's controller by reversing the comments array, but it's not the cleanest way and it interferes with another option I added (limiting the comments displayed to the top five and then adding a "show more/less comments" toggle for records with more than 5 comments).

Ideally the comments should be retrieved in the correct order in the first place.

So where is the method for the this.model.get('commentlog') hiding?

 

thanks,
FrancescaS

 

  • Hi Francesca Shiekh

    It is defined at include/SugarObjects/implements/commentlog/vardefs.php

    So you can modify the attribute

    'order_by' => 'date_entered:asc',

    In the custom version of commentlog's vardefs.

    Take a look at method getTemplatePaths of include/SugarObjects/VardefsManager.php

    Regards

    André Lopes
    Lampada Global
    Skype: andre.lampada
  • Thank you André Lopes!

    I knew I could count on you!

    It worked like a charm!

    ....I'm never done learning!

    FrancescaS

  • Hi André Lopes,

    We are an OnDemand user so I tried to make a package to alter the sortorder. Unfortunately all I managed to do was break the field so that it reverted to a typical text field... lol.

    I copied a file called vardefs.php

    to /custom/include/SugarObjects/implements/commentlog/

    In it was:

    <?php

    $vardefs = array(
    'fields' => array(
    'commentlog' => array(
    'order_by' => 'date_entered:desc',
    ),
    ),
    );

    Any thoughts where I went wrong?

    Kind regards 

    Richard

  • ooh, looks like you did an override of the entire $vardefs array! 

    Try changing just the order for the particular field in question, my changes were made in:

    custom/include/SugarObjects/implements/commentlog/vardefs.php

    and the file looks like this:

    <?php
    $vardefs['fields']['commentlog']['order_by'] = 'date_entered:desc';

    FrancescaS

  • That is useful to know - thanks all

    I logged this with support and it is in as an enhancement request. Hopefully Sugar will action it promptly.

    Enhancement request 82710

    Neil

  • Hi Neil - i'm really interested in displaying comments in latest first and limiting the number of them on view. How do i follow this enhancement request?

    Kind regards john

  • Hi john mckenzie

    This is the Sugar Bug/Enhancement link

    SugarCRM Bug/Enhancement 82710 

    We successfully used Francesca Shiekh 's solution above - thanks Francesca

    Neil

  • To be fair the solution above for ordering the entries was André Lopes's.

    As for limiting how many display I did this by overriding the commentlog field controller, I decided to show the latest 5 by default then allow them the option to view all. With more work you could link the number to a setting and paginate the results. I also reduced the space between entries for a more compact view, I still need to do some work to align the comment with the author and name to save some space.

    custom/clients/base/fields/commentlog/commentlog.js

    ({
        fieldTag: 'textarea',

        /**
         * @inheritdoc
         */

        events: {
            'click [data-action=toggle]': 'toggleCollapsedEntry',
            'click [data-action=toggle-entries]': 'toggleNumEntries'
        },

        /**
         * Object to keep track of what comment entries are collapsed
         */

        collapsedEntries: undefined,
        showAll: undefined,
        showLessButton: false,
        showMoreButton: false,
        /**
         * Defaults
         */

        _defaultSettings: {
            max_display_chars: 500,
            max_display_entries: 5
        },

        /**
         * Called when initializing the field
         * @param options
         */

        initialize: function(options) {
            this._super('initialize', [options]);
            this.collapsedEntries = {};
            this.showAll = false;
            this._initSettings();
        },

        /**
         * Initialize settings, default settings are used when none are supplied
         * through metadata.
         *
         * @return {View.Fields.BaseCommentlogField} Instance of this field.
         * @protected
         */

        _initSettings: function() {
            var configSettings = {
                max_display_chars: app.config.commentlog.maxchars
            };
            this._settings = _.extend({}, this._defaultSettings, configSettings);
            return this;
        },

        /**
         * Called when rendering the field
         * @private
         */

        _render: function() {
            this.showCommentLog();
            this._super('_render'); // everything showing in the UI should be done before this line.
        },

        /**
         * Called when formatting the value for display
         * @param value
         */

        format: function(value) {
            return value;
        },

        /**
         * Builds model for handlebar to show pass commentlog messages in record view.
         * This should only be called when there is need to render past messages, only
         * when this.getFormattedValue() returns the data format for message.
         */

        showCommentLog: function() {
            var collection = this.model.get('commentlog');

            if (!collection) {
                return;
            }
            var comments = collection.models;
            if (comments){
                if(!this.showAll && comments.length > this._settings.max_display_entries){
                  //limit displayed entries to this._settings.max_display_entries
                  comments =  _.first(comments, this._settings.max_display_entries);
                  this.showMoreButton = true;
                  this.showLessButton = false;
                }else if(this.showAll && comments.length > this._settings.max_display_entries){
                  this.showMoreButton = false;
                  this.showLessButton = true;
                }else{
                  this.showMoreButton = false;
                  this.showLessButton = false;
                }
                this.msgs = [];
                // add readable time and user link to users
                _.each(comments, function(commentModel) {
                    var id = commentModel.get('id');
                    if (_.isUndefined(this.collapsedEntries[id])) {
                        this.collapsedEntries[id] = true;
                    }

                    var msg = {
                        id: commentModel.get('id'),
                        entry: commentModel.get('entry'),
                        entryShort: this._getShortComment(commentModel.get('entry')),
                        created_by_name: commentModel.get('created_by_name'),
                        collapsed: this.collapsedEntries[id],
                    };

                    msg.showShort = msg.entry !== msg.entryShort;

                    // to date display format
                    var enteredDate = app.date(commentModel.get('date_entered'));
                    if (enteredDate.isValid()) {
                        msg.entered_date = enteredDate.formatUser();
                    }

                    var link = commentModel.get('created_by_link');
                    if (link && link.id) {
                        if (app.acl.hasAccess('view', 'Employees', {acls: link._acl})) {
                            msg.href = '#' + app.router.buildRoute('Employees', link.id, 'detail');
                        }
                    } else if (commentModel.has('created_by')) {
                        msg.href = '#' + app.router.buildRoute('Employees', commentModel.get('created_by'), 'detail');
                    }

                    if (commentModel === this._newEntryModel) {
                        msg.isNew = true;
                    }
                    this.msgs.push(msg);
                }, this);
            }

            this.newValue = this._newEntryModel ? this._newEntryModel.get('entry') : '';
        },
        /**
         * Truncate the comment log entry so it is shorter than the max_display_chars
         * Only truncate on full words to prevent ellipsis in the middle of words
         * @param {string} comment The comment log entry to truncate
         * @return {string} the shortened version of an entry if it was originally longer than max_display_chars
         * @private
         */

        _getShortComment: function(comment) {
            if (comment.length > this._settings.max_display_chars) {

                var cut = comment.substring(0, this._settings.max_display_chars);
                // let's cut at a full word by checking we are at a whitespace char
                while (!(/\s/.test(cut[cut.length - 1])) && cut.length > 0) {
                    cut = cut.substring(0, cut.length - 1);
                }
                comment = cut;
            }

            return comment;
        },

        /**
         * Save the id in this.collapsedEntries to keep track of what entries are shortened on view or not
         * @param event
         */

        toggleCollapsedEntry: function(event) {
            var id = $(event.currentTarget).data('commentId');
            this.collapsedEntries[id] = !this.collapsedEntries[id];
            this._render();
        },
        toggleNumEntries: function(event){
          this.showAll = $(event.currentTarget).data('showall');
          this._render();
        },
        /**
         * Called when unformatting the value for storage
         * @param value
         */

        unformat: function(value) {
            return value;
        },

        /**
         * @inheritdoc
         */

        bindDomChange: function() {
            if (!(this.model instanceof Backbone.Model)) {
                return;
            }

            var el = this.$el.find(this.fieldTag);

            var self = this;

            el.on('change', function() {
                var value = self.unformat(el.val());

                if (!self._newEntryModel) {
                    var collectionField = self.model.get('commentlog');

                    if (!collectionField) {
                        self.model.set(self.name, []);
                        collectionField = self.model.get('commentlog');
                    }

                    self._newEntryModel = app.data.createRelatedBean(self.model, null, 'commentlog_link', {
                        entry: value,
                        _link: 'commentlog_link',
                    });

                    collectionField.add(self._newEntryModel);
                }

                self._newEntryModel.set('entry', value);
            });
        },


        /**
         * @inheritdoc
         */

        bindDataChange: function() {
            if (this.model) {
                var collectionField = this.model.get(this.name);
                if (collectionField) {
                    this.listenTo(collectionField, 'reset', function() {
                        this.newValue = this._newEntryModel = null;
                    });
                }
                this.model.on('change:' + this.name, function(model, value) {
                    if (this.action !== 'edit') {
                        this.newValue = this._newEntryModel = null;
                    }
                    this._render();
                }, this);
            }
        },
    })

    custom/clients/base/fields/commentlog/detail.hbs

    <div class="commentLog detail" data-name="{{name}}" name="{{name}}">
        {{#each msgs}}
            <div class="msg-div toggle-text">
                <span class="ellipsis_inline" title data-placement="bottom" data-fieldname="author_name">
                    {{#if href}}
                        <a title="{{created_by_name}}" href="{{href}}">{{created_by_name}}</a>
                    {{else}}
                        {{created_by_name}}
                    {{/if}}
                    {{entered_date}}
                </span>
                {{#if showShort}}
                    {{#if collapsed}}
                        <div class="msg-content">{{entryShort}}...</div>
                        <button data-action="toggle" class="btn btn-link btn-invisible toggle-text" data-comment-id="{{id}}">
                            {{str 'LBL_COMMENT_LOG_SHOW_MORE' ../module}}
                        </button>
                    {{else}}
                        <div class="msg-content">{{entry}}</div>
                        <button data-action="toggle" class="btn btn-link btn-invisible toggle-text" data-comment-id="{{id}}">
                            {{str 'LBL_COMMENT_LOG_SHOW_LESS' ../module}}
                        </button>
                    {{/if}}
                {{else}}
                    <div class="msg-content">{{entry}}</div>
                {{/if}}
            </div>
         <hr style = "margin: 0.1em auto;" >
        {{/each}}
        {{#if showLessButton}}
          <button data-action="toggle-entries" class="btn btn-link btn-invisible toggle-text" data-showall="false">
            {{str 'LBL_COMMENT_LOG_SHOW_LESS_ENTRIES' ../module}}
          </button>
        {{/if}}
        {{#if showMoreButton}}
          <button data-action="toggle-entries" class="btn btn-link btn-invisible toggle-text" data-showall="true">
            {{str 'LBL_COMMENT_LOG_SHOW_MORE_ENTRIES' ../module}}
          </button>
        {{/if}}
    </div>

    custom/clients/base/fields/commentlog/edit.hbs

    <div class="commentLog edit" data-name="{{name}}" name="{{name}}">
        <div class="new-msg-div edit">
            <textarea rows="5" name="{{name}}">{{newValue}}</textarea>
        </div>
        {{#each msgs}}
            {{#unless isNew}}
            <div class="msg-div toggle-text">
                <span class="ellipsis_inline" title data-placement="bottom" data-fieldname="author_name">
                    {{#if href}}
                        <a title="{{created_by_name}}" href="{{href}}">{{created_by_name}}</a>
                    {{else}}
                        {{created_by_name}}
                    {{/if}}
                    {{entered_date}}
                </span>
                <div class="msg-content">{{entry}}</div>
            </div>
            {{/unless}}
          <hr style = "margin: 0.1em auto;" >
        {{/each}}
    </div>

     

  • Hi All,

    How i can make same field as comment log in same module.

    i need one more filed like comment log behavior in same module.

    Ex- comment log-1

          Comment Log-2

    it it possible that we can add one more comment field in module with different name.

    Thanks