How to add cc emails to new email

Hello,

  I need to find a way to include the people that are CC'ed in an email to appear when they email form the record view.

They then click the plus btn to generate a new email and this div appears to do that.

How would I start the process of automatically adding the CC'ed peoples to this view?

So to clarify I want the people that were CC'ed before in the case's history to automatically appear when clicking the plus btn and the user won't need to do it manually then.

Best Regards

James Palmisano

Parents
  • I had a similar requirement, the problem is that when you clcick the + on the Email subpanel on Cases you don't know WHICH email you are replying to.

    I solved the issue by creating a "reply all" option in rowactions ( on each line of the Email Subpanel ), by selecting that reply you know which email you are replying to.

    It was not easy.

    In

    custom/modules/Emails/clients/base/views/<your cases subpanel view>/<your cases subpanel view>.php

    I added three custom email actions: reply, reply all and forward (opendetails ia a custom view of the email thread)

    They behave as you would expect in an email client.

      'rowactions' => array (
        'actions' => array (
          array(
            'type' => 'rowaction',
            'css_class' => 'btn',
            'event' => 'list:customemailreply:fire',
            'tooltip' => 'Reply to email',
            'icon' => 'fa-reply',
            'acl_action' => 'create',
          ),
          array(
            'type' => 'rowaction',
            'event' => 'list:customemailreplyall:fire',
            'label'=>'LBL_REPLY_ALL',
            'tooltip' => 'Reply All',
            'icon' => 'fa-mail-reply-all',
            'acl_action' => 'create',
          ),
          array(
            'type' => 'rowaction',
            'event' => 'list:customemailforward:fire',
            'label'=>'LBL_FORWARD',
            'tooltip' => 'forward',
            'icon' => 'fa-mail-forward',
            'acl_action' => 'create',
          ),
    
          array(
            'type' => 'rowaction',
            'event' => 'list:opendetails:fire',
            'label' => 'LBL_OPEN_EMAIL_DETAILS',
            'tooltip' => 'Read email',
            'acl_action' => 'create',
          ),
        ),
    

     

    In the controller for the same view:

    custom/modules/Emails/clients/base/views/<your cases subpanel view>/<your cases subpanel view>.js

    I defined the actions to be taken when each of the events is fired.

    ({
      extendsFrom:'SubpanelListView',
      initialize: function(options){
        this._super('initialize', [options]);
        this.context.on('list:customemailreply:fire',this.customReplyClicked);
        this.context.on('list:customemailreplyall:fire',this.customReplyAllClicked);
        this.context.on('list:customemailforward:fire',this.customForwardClicked);
        this.context.on('list:opendetails:fire',this.opendetailsClicked);
      },
      opendetailsClicked: function(emailModel){
        //show progress message
        app.alert.show('loading-details', {
          level: 'info',
          messages: 'Loading details...',
          autoClose: false
        });
        var url = app.api.buildURL('getCustomEmailDetails/'+emailModel.get('id'));
        app.api.call('read', url, null, {
          success: _.bind(function(data) {
            console.log(data);
            app.alert.dismiss('loading-details');
            app.drawer.open({
              layout:'custom-email-detail',
              context:{
                emailDetails: data,
              }
            });
          })
        });
      },
      customForwardClicked: function(emailModel){
        var caseModel = this.get('parentModel'),
            caseId = caseModel.get('id'),
            emailType = emailModel.get('status');
        if(emailType == 'draft'){
          emailModel.set('isNotEmpty', true);
          //editing a draft
          //open the drawer with the email  as was when last saved
          app.drawer.open({
            layout:'compose',
            context:{
              create: false,
              model: emailModel,
              module: 'Emails',
            }
          },this);
        }else{
          var emailId = emailModel.get('id'),
              messageType = 'forward',//internal, reply, replyAll, forward or new
              url = app.api.buildURL('Emails/getCustomCompose/'+messageType+'/'+caseId+'/'+emailId);
          //new forwardpre-populate some information
          App.api.call('GET', url, '',{
            success: _.bind(function(o){
              app.drawer.open({
                layout:'compose',
                context:{
                  create: true,
                  prepopulate: o ,
                  module:'Emails',
                }
              });
            }, this),
            error: _.bind(function(o){
              console.log(o);
            }, this),
          });
        }
      },
      customReplyAllClicked: function(emailModel){
        var caseModel = this.get('parentModel'),
            caseId = caseModel.get('id'),
            emailType = emailModel.get('status');
        if(emailType == 'draft'){
          emailModel.set('isNotEmpty', true);
          //editing a draft
          //open the drawer with the email  as was when last saved
          app.drawer.open({
            layout:'compose',
            context:{
              create: false,
              model: emailModel,
              module: 'Emails',
            }
          },this);
        }else{
          var emailId = emailModel.get('id'),
              messageType = 'replyAll',//internal, reply, replyAll or new
              url = app.api.buildURL('Emails/getCustomCompose/'+messageType+'/'+caseId+'/'+emailId);
          //new reply pre-populate some information
          App.api.call('GET', url, '',{
            success: _.bind(function(o){
              app.drawer.open({
                layout:'compose',
                context:{
                  create: true,
                  prepopulate: o ,
                  module:'Emails',
                }
              });
            }, this),
            error: _.bind(function(o){
              console.log(o);
            }, this),
          });
        }
      },
      customReplyClicked: function(emailModel){
        var caseModel = this.get('parentModel'),
            caseId = caseModel.get('id'),
            emailType = emailModel.get('status');
        if(emailType == 'draft'){
          emailModel.set('isNotEmpty', true);
          //editing a draft
          //open the drawer with the email  as was when last saved
          app.drawer.open({
            layout:'compose',
            context:{
              create: false,
              model: emailModel,
              module: 'Emails',
            }
          },this);
        }else{
          var emailId = emailModel.get('id'),
              messageType = 'reply',//internal, reply, replyAll or new
              url = app.api.buildURL('Emails/getCustomCompose/'+messageType+'/'+caseId+'/'+emailId);
          //new reply pre-populate some information
          App.api.call('GET', url, '',{
            success: _.bind(function(o){
              app.drawer.open({
                layout:'compose',
                context:{
                  create: true,
                  prepopulate: o ,
                  module:'Emails',
                }
              });
            }, this),
            error: _.bind(function(o){
              console.log(o);
            }, this),
          });
        }
      }
    });
    

    As you can see the actions use a CustomCompose, which is the custom API that takes care of setting the necessary variables for the drawer to prepopulate with the necessary information

    in custom/modules/Emails/clients/base/api/getCustomComposeApi.php

    (I have some additional custom compose here for panel-top emails actions such as Internal Compose, and Custom Compose which are panel-top actions that are not specific to an email).

    <?php
    class getCustomComposeApi extends SugarApi
    {
      public function registerApiRest(){
        return array(
          'getCustomCompose' => array(
            // What type of HTTP request to match against, we support GET/PUT/POST/DELETE
            'reqType' => 'GET',
            // This is the path you are hoping to match, it also accepts wildcards of ? and <module>
            'path' => array('Emails', 'getCustomCompose', '?','?','?'),
            // These take elements from the path and use them to populate $args
            'pathVars' => array('','','type','caseId', 'emailId'),
            // This is the method name in this class that the url maps to
            'method' => 'getCustomCompose',
            // The shortHelp is vital, without it you will not see your endpoint in the /help
            'shortHelp' => 'Generates options for Email Reply button on subpanel in cases module',
            // The longHelp points to an HTML file and will be there on /help for people to expand and show
            'longHelp' => '',
          ),
        );
      }
    
      /**
       * Generate the Custom compose data package consumed by the quick compose screens.
       *
       * @param Array $data
       * @param $data['email_id'] email The BeanID for the Email we are replying to
       * @param $data['parent_id'] is assumed to be a Case ID
       * @param $type internal = send to Engineers, new = send to user, use case data likely no email to reply to, reply = copy original email .
       */
      function getCustomCompose($api, $args){
        global $current_user, $app_list_strings;
        $data = array();
        $data['email_id']= !empty($args['emailId'])?$args['emailId']:'';
        $data['parent_id']=$args['caseId'];
        $type = $args['type'];
        $toAddresses = array();
        $ccAddresses = array();
        //need to retrieve the full case bean, not all the bean values are pulled in the "bean"
        $case = BeanFactory::retrieveBean('Cases',$data['parent_id']);
        $parent_id = $case->id;
        $parent_type = 'Cases';
        if($type== 'new'){
          $GLOBALS['log']->debug("CustomCompose:: New");
          //NEW EMAIL to Customers
          //send the email TO all contacts on the case, eliminate duplicates
          //default in the from address, this is needed especially for cases from forms that don't have
          //any matching contacts
          $rel = 'contacts';
          $case->load_relationship($rel);
          foreach($case->$rel->getBeans() as $contact){
            $sea = BeanFactory::newBean('EmailAddresses');
            $email_addr = $sea->getPrimaryAddress($contact);
            $toAddresses[]=array(
              'email'=>$email_addr,
              'module'=> 'Contacts',
              'name'=>$contact->full_name
            );
          }
          //add the address from the case if valid
          //sugar should take care not to send duplicates 
          if(isset($case->case_from_addr_c) && filter_var($case->case_from_addr_c, FILTER_VALIDATE_EMAIL)){
            $toAddresses[]=array(
              'email'=>$case->case_from_addr_c,
              'module'=> '',
              'name'=>$case->case_from_addr_c
            );
          }
          //set up the BODY of the email as a copy of the case description
          $preBodyHTML = "<div><br><br><br> <hr></div>" . "<i><small>On: " . $case->date_entered . " " . $case->case_from_addr_c . " submitted the following Case:</small></i><br />";
          $order   = array("\r\n", "\n", "\r");
          $replace = '<br />';
          //default the body to the description of the case
          //in case we use this from panel-top
          $body = str_replace($order, $replace,$case->description);
          if(strpos($case->name, str_replace('%1',$case->case_number,$case->getEmailSubjectMacro()))===FALSE){
            //set the SUBJECT with the case macro valid for all compose types
            $subject=str_replace('%1', $case->case_number, $case->getEmailSubjectMacro() . " ". $case->name);
          }else{
             $subject = $case->name;
          }
          if(!preg_match('/^(re:)+/i', $subject)) {
            $subject = "RE: {$subject} ";
          }
        }elseif($type == 'internal'){
          $GLOBALS['log']->debug("CustomCompose:: internal");
           //INTERNAL EMAIL to Case Engineers
           //send the email TO all engineers on the case, eliminate duplicates
           $rel = 'cases_users_1';
           $case->load_relationship($rel);
           $toAddresses = array();
           foreach($case->$rel->getBeans() as $user){
             $sea = BeanFactory::newBean('EmailAddresses');
             $email_addr = $sea->getPrimaryAddress($user);
             if(!empty($email_addr)){
               $GLOBALS['log']->debug("add user to To address:" . $email_addr);
               $toAddresses[]=array(
                 'email'=>$email_addr,
                 'module'=> 'Users',
                 'name'=>$user->user_name
               );
             }
           }
           //get assigned user info
           if(!empty($case->assigned_user_id)){
             $auser = BeanFactory::retrieveBean('Users', $case->assigned_user_id);
             //add the assigned user to the To
             //the To cannot be empty, if there is no one the system will add the original customer
             $sea = BeanFactory::newBean('EmailAddresses');;
             $aemail_addr = $sea->getPrimaryAddress($auser);
             $GLOBALS['log']->debug("add user to To address:" . $aemail_addr);
             if(!empty($aemail_addr)){
               $toAddresses[]=array(
                 'email'=>$aemail_addr,
                 'module'=> 'Users',
                 'name'=>$auser->user_name
               );
             }
           }
           // add current user
           $cea = BeanFactory::newBean('EmailAddresses');;
           $cemail_addr = $cea->getPrimaryAddress($current_user);
           $GLOBALS['log']->debug("add user to To address:" . $cemail_addr);
           if(!empty($cemail_addr)){
              $toAddresses[]=array(
                'email'=>$cemail_addr,
                'module'=> 'Users',
                'name'=>$current_user->user_name
              );
           }
           if (empty($auser)) $auser = $current_user;
           //get primary contact info for body
           $contact = BeanFactory::retrieveBean('Contacts',$case->contact_id_c);
           //get Account info for body
           $account = BeanFactory::retrieveBean('Accounts',$case->account_id);
           $order   = array("\r\n", "\n", "\r");
           $replace = '<br />';
           $preBodyHTML =<<<BODY
    <pre>
    ================================================
         This is a posting from Technical Support
    ================================================
             Engineer: {$auser->first_name} {$auser->last_name}
                        speaking for...
             Customer: {$contact->full_name}
         Organization: {$account->name}
              Product: {$app_list_strings['case_product_dd'][$case->case_product_c]}
              Version: {$case->case_product_version_c}
             Platform: {$app_list_strings['product_platforms_list_DD'][$case->case_platform_c]}
        Date Received: {$case->date_entered}
    
    Technical Summary:
    
            {$case->case_summary_c}
    
          Description:
    
            {$case->description}
    ------------------------------------------------
    </pre>
    BODY;
          $body = '';
          //set the SUBJECT with the case macro valid for all compose types
          if(strpos($case->name, str_replace('%1',$case->case_number,$case->getEmailSubjectMacro()))===FALSE){
            //set the SUBJECT with the case macro valid for all compose types
            $subject=str_replace('%1', $case->case_number, $case->getEmailSubjectMacro() . " ". $case->name);
          }else{
             $subject = $case->name;
          }
          if(!preg_match('/^(re:)+/i', $subject)) {
            $subject = "RE: {$subject} ";
          }
        }elseif($type == 'reply' && !empty($data['email_id'])){
          $GLOBALS['log']->debug("CustomCompose:: as Reply to emailID " .$data['email_id']);
          //assume it's a reply message TO the original sender of the email in question
          //or a draft
          $ie = BeanFactory::retrieveBean('Emails',$data['email_id']);
          if($ie->type == 'draft'){
            //return the draft as is
            return;
          }else{
            //not a draft, composing a reply
            //set the recipient as the reply-to or from of the original message
            //unless it's from the queue
            if((!empty($ie->reply_to_email) && $ie->reply_to_email!=$case->case_queue_c) ||
               (!empty($ie->from_addr) && $ie->from_addr !=$case->case_queue_c)){
              $email_addr = !empty($ie->reply_to_email)?$ie->reply_to_email:$ie->from_addr;
            }else{
              $email_addr = $ie->to_addrs;
            }
            $GLOBALS['log']->debug('$email_addr = ' . $email_addr);
            $name = !empty($ie->reply_to_addr)?$ie->reply_to_addr:$email_addr;
            $GLOBALS['log']->debug('$name = ' . $name);
            if(!empty($email_addr)){
              $toAddresses[]=array(
                'email'=>$email_addr,
                'module'=> '',
                'name'=>$name,
              );
            }
            //include Cc'd addresses?
    
            //include Case Contacts
    /*
            $case = BeanFactory::retrieveBean('Cases',$data['parent_id']);
            $parent_id = $case->id;
            $parent_type = 'Cases';
            $rel = 'contacts';
            $case->load_relationship($rel);
            foreach($case->$rel->getBeans() as $contact){
              $sea = BeanFactory::newBean('EmailAddresses');;
              $email_addr = $sea->getPrimaryAddress($contact);
              $toAddresses[]=array(
                'email'=>$email_addr,
                'module'=> 'Contacts',
                'name'=>$contact->full_name
              );
            }
    */
            //use the BODY of the original message in the email
            $description = '';
            if(!empty($ie->description)){
              $description = $ie->description;
            }elseif(!empty($ie->description_html)){
              $description = $ie->description_html;
            }
            $GLOBALS['log']->debug('description = ' . $description);
            $preBodyHTML = " <div><br><br><br><hr></div>";
            $order   = array("\r\n", "\n", "\r");
            $replace = '<br />';
            $body = str_replace($order, $replace,$description);
            //the email should come FROM the queue, not the individual
            //we override the default in custom/modules/Emails/clients/base/api/sender/sender.js
            if(strpos($ie->name, str_replace('%1',$case->case_number,$case->getEmailSubjectMacro()))===FALSE){
              $subject=str_replace('%1', $case->case_number, $case->getEmailSubjectMacro() . " ". $ie->name);
            }else{
              $subject=$ie->name;
            }
            if(!preg_match('/^(re:)+/i', $subject)) {
              $subject = "RE: {$subject} ";
            }
          }
        }elseif($type == 'replyAll' && !empty($data['email_id'])){
          $GLOBALS['log']->debug("CustomCompose:: as Reply to emailID " .$data['email_id']);
          //assume it's a reply message TO the original sender of the email in question
          //or a draft
          $ie = BeanFactory::retrieveBean('Emails',$data['email_id']);
          if($ie->type == 'draft'){
            //return the draft as is
            return;
          }else{
            //not a draft, composing a reply
            //set the recipient as the reply-to or from of the original message
            $email_addr = !empty($ie->reply_to_email)?$ie->reply_to_email:$ie->from_addr;
            $GLOBALS['log']->debug('$email_addr = ' . $email_addr);
            $name = !empty($ie->reply_to_addr)?$ie->reply_to_addr:$email_addr;
            $GLOBALS['log']->debug('$name = ' . $name);
            if(!empty($email_addr)){
              $toAddresses[]=array(
                'email'=>$email_addr,
                'module'=> '',
                'name'=>$name,
              );
            }
    
            //include Cc
            $email_addr_cc = !empty($ie->cc_addrs)?$ie->cc_addrs:'';
            $GLOBALS['log']->debug('$email_addr_cc = ' . $email_addr_cc);
            $name = !empty($ie->cc_addrs)?$ie->cc_addrs:'';
            $GLOBALS['log']->debug('$name = ' . $name);
            if(!empty($email_addr_cc)){
              $ccAddresses[]=array(
                'email'=>$email_addr,
                'module'=> '',
                'name'=>$name,
              );
            }
    
    
            //use the BODY of the original message in the email
            $description = '';
            if(!empty($ie->description)){
              $description = $ie->description;
            }elseif(!empty($ie->description_html)){
              $description = $ie->description_html;
            }
            $GLOBALS['log']->debug('description = ' . $description);
            $preBodyHTML = " <div><br><br><br><hr></div>";
            $order   = array("\r\n", "\n", "\r");
            $replace = '<br />';
            $body = str_replace($order, $replace,$description);
            //the email should come FROM the queue, not the individual
            //we override the default in custom/modules/Emails/clients/base/api/sender/sender.js
            if(strpos($ie->name, str_replace('%1',$case->case_number,$case->getEmailSubjectMacro()))===FALSE){
              $subject=str_replace('%1', $case->case_number, $case->getEmailSubjectMacro() . " ". $ie->name);
            }else{
              $subject=$ie->name;
            }
            if(!preg_match('/^(re:)+/i', $subject)) {
              $subject = "RE: {$subject} ";
            }
          }
    
        }elseif($type == 'forward' && !empty($data['email_id'])){
          $GLOBALS['log']->debug("CustomCompose:: as Forward emailID " .$data['email_id']);
          $ie = BeanFactory::retrieveBean('Emails',$data['email_id']);
          if($ie->type == 'draft'){
            //return the draft as is
            return;
          }else{
            //not a draft, composing a forward
            //no recipient therefore set to current user or the system will default customer
            // add current user
            $cea = BeanFactory::newBean('EmailAddresses');;
            $cemail_addr = $cea->getPrimaryAddress($current_user);
            $GLOBALS['log']->debug("add user to To address:" . $cemail_addr);
            if(!empty($cemail_addr)){
               $toAddresses[]=array(
                 'email'=>$cemail_addr,
                 'module'=> 'Users',
                 'name'=>$current_user->user_name
               );
            }
            //use the BODY of the original message in the email
            $description = '';
            if(!empty($ie->description)){
              $description = $ie->description;
            }elseif(!empty($ie->description_html)){
              $description = $ie->description_html;
            }
            $GLOBALS['log']->debug('description = ' . $description);
            $ie = BeanFactory::retrieveBean('Emails',$data['email_id']);
    
            $preBodyHTML =<<<FWD
    <pre>
    ---------- Forwarded message ----------
    From: {$ie->from_addr}
    Date: {$ie->date_sent} (UTC)
    Subject: {$ie->name}
    To: {$ie->to_addrs}
    </pre>
    FWD;
            $order   = array("\r\n", "\n", "\r");
            $replace = '<br />';
            $body = str_replace($order, $replace,$description);
            //the email should come FROM the queue, not the individual
            //we override the default in custom/modules/Emails/clients/base/api/sender/sender.js
            if(strpos($ie->name, str_replace('%1',$case->case_number,$case->getEmailSubjectMacro()))===FALSE){
              $subject=str_replace('%1', $case->case_number, $case->getEmailSubjectMacro() . " ". $ie->name);
            }else{
              $subject=$ie->name;
            }
            if(!preg_match('/^(fwd:)+/i', $subject)) {
              $subject = "Fwd: {$subject} ";
            }
          }
    
        }
    
        //build the return the package
        $composePackage = array(
          'to_addresses' => $toAddresses,
          'cc_addresses' => $ccAddresses,
          'parent_type'      => 'Cases',
          'parent_id'        => $case->id,
          'parent_name'    => $case->name,
          'subject'  => $subject,
          'html_body'        => $preBodyHTML . $body,
          'body'             => $preBodyHTML . $body,
          'attachments'      => array(),
          //'email_id'       => (isset($email_id)?$email_id:''),
          //'email_config'   => $fromAddress,
        );
        //the compose needs some additional information to get the preview 
        if($type == 'reply') $composePackage['related'] = array('parent_id'=>$case->id, 'parent_type'=>'Cases');
        foreach ($composePackage as $key => $singleCompose)
        {
          if (is_string($singleCompose)) $composePackage[$key] = str_replace(" ", " ", from_html($singleCompose));
        }
        return ($composePackage);
      }
    }
    

    Note that we also override the sender of the email to be the queue - we don't send out Case emails from individuals but queues:

    custom/modules/Emails/clients/base/fields/sender/sender.js (I have the wrong path in the code comments above line 347)

    Note that it uses the "case_queue_c" field in Cases (a custom field) that is populated with the email address of the case queue in a logic hook when the Case is created (another adventure, see: https://community.sugarcrm.com/message/81897#comment-81897 )

    ({
        fieldTag: 'input.select2',
        initialize: function(options) {
            _.bindAll(this);
            app.view.Field.prototype.initialize.call(this, options);
            this.endpoint = this.def.endpoint;
        },
        _render: function() {
            var result = app.view.Field.prototype._render.call(this);
            if (this.tplName === 'edit') {
                var action = (this.endpoint.action) ? this.endpoint.action : null,
                    attributes = (this.endpoint.attributes) ? this.endpoint.attributes : null,
                    params = (this.endpoint.params) ? this.endpoint.params : null,
                    myURL = app.api.buildURL(this.endpoint.module, action, attributes, params);
                app.api.call('GET', myURL, null, {
                    success: this.populateValues,
                    error:   function(error) {
                        app.alert.show('server-error', {
                            level: 'error',
                            messages: 'ERR_GENERIC_SERVER_ERROR'
                        });
                        app.error.handleHttpError(error);
                    }
                });
            }
            return result;
        },
        populateValues: function(results) {
            var self = this,
                defaultResult,
                defaultValue = {},
                parentMod = this.context.parent,
                parentModule = parentMod.get('module'),
                queue = ('('+parentMod.get('model').get('case_queue_c')+')').replace(/[.*+?^${}()|[\]\\]/g, "\\$&");;
            if (this.disposed === true) {
                return; //if field is already disposed, bail out
            }
            if (!_.isEmpty(results)) {
                if(parentModule == 'Cases' && typeof(queue)!= 'undefined'){
                  var pattern = new RegExp('.*'+queue+'.*');
                  defaultResult = _.find(results, function(result) {
                    return result.display.match(pattern);
                  });
                }else{
                  defaultResult = _.find(results, function(result) {
                    return result.default;
                  });
                }
                defaultValue = (defaultResult) ? defaultResult : results[0];
                if (!this.model.has(this.name)) {
                    this.model.set(this.name, defaultValue.id);
                }
            }
            var format = function(item) {
                return item.display;
            };
            this.$(this.fieldTag).select2({
                data:{ results: results, text: 'display' },
                formatSelection: format,
                formatResult: format,
                width: '100%',
                placeholder: app.lang.get('LBL_SELECT_FROM_SENDER', this.module),
                initSelection: function(el, callback) {
                    if (!_.isEmpty(defaultValue)) {
                          callback(defaultValue);
                    }
                }
            }).on("change", function(e) {
                if (self.model.get(self.name) !== e.val) {
                    self.model.set(self.name, e.val, {silent: true});
                }
            });
    
            this.$(".select2-container").addClass("tleft");
        },
    
      /**
       * {@inheritdoc}
       *
       * We need this empty so it won't affect refresh the select2 plugin
       */
      bindDomChange: function() {
      }
    })
    

    HTH, comments welcome.
    FrancescaS

  • This is the first answer that I have received about sugar that is extremely useful.  Thank you so much for your comment!  I have not implemented what you suggested yet, but I will let you know what happens.

Reply Children
No Data