Tuesday, September 07, 2010

Adding AJAX support in Module Builder's "Edit Relationship" in SugarCrm

In SugarCRM custom modules the default buttons in a subpanel are "Create" and "Select". In the framework SugarCrm is built on top there is support for AJAX / inline create in the subpanel as well as the normal full form create. There are also support for single row selection and multiple row selection. To utilize this you need to have knowledge about the various *defs.php files that are code generated by module builder and SugarCrm.

This hack shows how to add support for these buttons in Module Builder. We are going to UI support for selecting what buttons you want to show in your module's subpanel, the different buttons are AJAX Quick Create Button, Full Form Create Button, AJAX Single Select Button and/or AJAX Multiple Select Button.

After the hack is implemented your Edit Relationsship screen in Module Builder is going to look like the following.



After selecting required buttons save the changes, deploy the package (with the affected modules inside) to see the effect. The following screenshot shows the M1 Subpanel on M2 module where we have selected a Quick Create button.



The following screen shows the M2 Subpanel on M1 module where we have selected a Quick Create and Multi Select button.







Likewise we can select any combination we want for our subpanel. (apart from both having a single and a multiple select button - which I did not think made a lot of sense).

This hack is not upgrade safe.




This is the subversion diff file that outlines the changes made to a SugarCrm 5.5.2 code base to achieve the features described above.





Index: modules/ModuleBuilder/javascript/ModuleBuilder.js
===================================================================
--- modules/ModuleBuilder/javascript/ModuleBuilder.js (revision 1)
+++ modules/ModuleBuilder/javascript/ModuleBuilder.js (working copy)
@@ -872,7 +872,10 @@
     ajaxStatus.hideStatus();
     var tab = ModuleBuilder.findTabById('relEditor');
     tab.set("content", o.responseText);
-    SUGAR.util.evalScript(tab);
+    //SUGAR.util.evalScript(tab);
+    //Hack Relations between modules
+    SUGAR.util.evalScript(o.responseText);
+                //Hack Relations between modules
    });
   },
   moduleDropDown: function(name, field){
Index: modules/ModuleBuilder/language/en_us.lang.php
===================================================================
--- modules/ModuleBuilder/language/en_us.lang.php (revision 1)
+++ modules/ModuleBuilder/language/en_us.lang.php (working copy)
@@ -627,6 +627,12 @@
                 'encrypt'=>'Encrypt'
 ),
 
-'parent' => 'Flex Relate'
+'parent' => 'Flex Relate',
+//Hack Relations between modules
+'LBL_AJAX_QUICK_CREATE_BTN' => 'AJAX Quick Create Button',
+'LBL_AJAX_SINGLE_SELECT_BTN' => 'AJAX Single Select Button',
+'LBL_AJAX_MULTIPLE_SELECT_BTN' => 'AJAX Multiple Select Button',
+'LBL_FULL_FORM_CREATE_BTN' => 'Full Form Create Button',
+//Hack Relations between modules
 );
 
Index: modules/ModuleBuilder/parsers/relationships/AbstractRelationship.php
===================================================================
--- modules/ModuleBuilder/parsers/relationships/AbstractRelationship.php (revision 1)
+++ modules/ModuleBuilder/parsers/relationships/AbstractRelationship.php (working copy)
@@ -80,6 +80,7 @@
         'relationship_type' , 
         'relationship_role_column' , 
         'relationship_role_column_value' , 
+        'ext1' ,  //Hack Relations between modules
         'reverse' ) ;
 
     /*
@@ -263,12 +264,52 @@
   }else{
    $subpanelDefinition [ 'title_key' ] = 'LBL_' . strtoupper ( $relationshipName . '_FROM_' . $sourceModule ) . '_TITLE' ;
   }
-        $subpanelDefinition [ 'get_subpanel_data' ] = $relationshipName ;
-        $subpanelDefinition [ 'top_buttons' ] = array(
+  $subpanelDefinition [ 'get_subpanel_data' ] = $relationshipName ;
+  //Hack Relations between modules
+  if(isset($this->definition['ext1']) AND $this->definition['ext1'] != ''){
+   $topBtnOption = explode('_@@_', $this->definition['ext1']);
+   // LHS Module
+   if ($this->definition['lhs_module'] == $sourceModule){
+    // Quick Create Button
+    if($topBtnOption[0] == '1'){
+     $subpanelDefinition [ 'top_buttons' ][] = array('widget_class' => 'SubPanelTopButtonQuickCreate');
+    }
+    // Full Form Create Button
+    if($topBtnOption[1] == '1'){
+     $subpanelDefinition [ 'top_buttons' ][] = array('widget_class' => 'SubPanelTopCreateButton');
+    }
+    // Single Select Button
+    if($topBtnOption[2] == '1'){
+                    $subpanelDefinition [ 'top_buttons' ][] = array('widget_class' => 'SubPanelTopSelectButton');
+    }
+    // Multiple Select Button
+    if($topBtnOption[3] == '1'){
+                        $subpanelDefinition [ 'top_buttons' ][] = array('widget_class' => 'SubPanelTopSelectButton', 'popup_module' => $this->definition['rhs_module'], 'mode' => 'MultiSelect', 'initial_filter_fields' => array());
+    }
+   }else{
+    // Quick Create Button
+    if($topBtnOption[4] == '1'){
+     $subpanelDefinition [ 'top_buttons' ][] = array('widget_class' => 'SubPanelTopButtonQuickCreate');
+    }
+    // Full Form Create Button
+    if($topBtnOption[5] == '1'){
+     $subpanelDefinition [ 'top_buttons' ][] = array('widget_class' => 'SubPanelTopCreateButton');
+    }
+    // Single Select Button
+    if($topBtnOption[6] == '1'){
+                    $subpanelDefinition [ 'top_buttons' ][] = array('widget_class' => 'SubPanelTopSelectButton');
+    }
+    // Multiple Select Button
+    if($topBtnOption[7] == '1'){
+                        $subpanelDefinition [ 'top_buttons' ][] = array('widget_class' => 'SubPanelTopSelectButton', 'popup_module' => $this->definition['lhs_module'], 'mode' => 'MultiSelect', 'initial_filter_fields' => array());                        
+    }
+   }
+  }
+  /*$subpanelDefinition [ 'top_buttons' ] = array(
       array('widget_class' => "SubPanelTopCreateButton"),
       array('widget_class' => 'SubPanelTopSelectButton', 'mode'=>'MultiSelect')
-  );
-        
+  );*/
+        //Hack Relations between modules
         return array ( $subpanelDefinition );
     }   
     
Index: modules/ModuleBuilder/parsers/relationships/AbstractRelationships.php
===================================================================
--- modules/ModuleBuilder/parsers/relationships/AbstractRelationships.php (revision 1)
+++ modules/ModuleBuilder/parsers/relationships/AbstractRelationships.php (working copy)
@@ -151,7 +151,21 @@
                     $this->delete ( $_REQUEST [ 'relationship_name' ] ) ;
         }
         }
-        
+  //Hack Relations between modules
+  $buttonArr = array('lhs_quick_create', 'lhs_full_form_create','lhs_signle_select', 'lhs_multiple_select', 'rhs_quick_create',
+                     'rhs_full_form_create', 'rhs_signle_select', 'rhs_multiple_select');
+  $ext1 = '';
+  foreach($buttonArr as $option){
+   $btn = false;
+   if(isset($_REQUEST[$option]) AND $_REQUEST[$option] == '1'){
+    $ext1 .= '1_@@_';
+   }else{
+    $ext1 .= '0_@@_';
+   }
+  }
+  $ext1 = substr($ext1, 0, (strlen($ext1) - 4));
+  $definition ['ext1'] = $ext1;
+  //Hack Relations between modules
         $newRelationship = RelationshipFactory::newRelationship ( $definition ) ;
         // TODO: error handling in case we get a badly formed definition and hence relationship
         $this->add ( $newRelationship ) ;
Index: modules/ModuleBuilder/tpls/studioRelationship.tpl
===================================================================
--- modules/ModuleBuilder/tpls/studioRelationship.tpl (revision 1)
+++ modules/ModuleBuilder/tpls/studioRelationship.tpl (working copy)
@@ -178,6 +178,45 @@
 
    {/if} {* subpanels etc for all but one-to-one relationships *}
    {/if} {* if relationship_only *}
+  {* Hack Relations between modules *}
+  {if $rel.relationship_type != 'one-to-one'}
+  <tr>
+   <td colspan=2>
+   {if $rel.relationship_type == 'many-to-many'}
+   <table class="listView"><tr><td class="listViewThS1">
+   {sugar_translate label=$rel.lhs_module} Subpanel On {sugar_translate label=$rel.rhs_module}
+   </td></tr>
+   <tr><td class="evenListRowS1">
+   <input type="checkbox" name="lhs_quick_create" id="lhs_quick_create" value="1" onclick="lock_create_option(this.id, 'lhs')" 
+   {if $ckBoxOption.0 == 1}checked{/if} /> {$mod_strings.LBL_AJAX_QUICK_CREATE_BTN}<br>
+   <input type="checkbox" name="lhs_full_form_create" id="lhs_full_form_create" value="1" onclick="lock_create_option(this.id, 'lhs')" 
+   {if $ckBoxOption.1 == 1}checked{/if} /> {$mod_strings.LBL_FULL_FORM_CREATE_BTN}<br>
+   <input type="checkbox" name="lhs_signle_select" id="lhs_signle_select" value="1" onclick="lock_multiple_select(this.id, 'lhs')" 
+   {if $ckBoxOption.2 == 1}checked{/if}/> {$mod_strings.LBL_AJAX_SINGLE_SELECT_BTN}<br>
+   <input type="checkbox" name="lhs_multiple_select" id="lhs_multiple_select" value="1" onclick="lock_multiple_select(this.id, 'lhs')" 
+   {if $ckBoxOption.3 == 1}checked{/if} /> {$mod_strings.LBL_AJAX_MULTIPLE_SELECT_BTN}<br>
+   </td></tr></table>
+   {/if}&nbsp;
+   </td>
+   <td>&nbsp;</td>
+   <td colspan=2>
+   <table class="listView"><tr><td class="listViewThS1">
+   {sugar_translate label=$rel.rhs_module} Subpanel On {sugar_translate label=$rel.lhs_module}
+   </td></tr>
+   <tr><td class="evenListRowS1">
+   <input type="checkbox" name="rhs_quick_create" id="rhs_quick_create" value="1" onclick="lock_create_option(this.id, 'rhs')" 
+   {if $ckBoxOption.4 == 1}checked{/if} /> {$mod_strings.LBL_AJAX_QUICK_CREATE_BTN}<br>
+   <input type="checkbox" name="rhs_full_form_create" id="rhs_full_form_create" value="1" onclick="lock_create_option(this.id, 'rhs')" 
+   {if $ckBoxOption.5 == 1}checked{/if} /> {$mod_strings.LBL_FULL_FORM_CREATE_BTN}<br>
+   <input type="checkbox" name="rhs_signle_select" id="rhs_signle_select" value="1" onclick="lock_multiple_select(this.id, 'rhs')" 
+   {if $ckBoxOption.6 == 1}checked{/if} /> {$mod_strings.LBL_AJAX_SINGLE_SELECT_BTN}<br>
+   <input type="checkbox" name="rhs_multiple_select" id="rhs_multiple_select" value="1" onclick="lock_multiple_select(this.id, 'rhs')" 
+   {if $ckBoxOption.7 == 1}checked{/if} /> {$mod_strings.LBL_AJAX_MULTIPLE_SELECT_BTN}
+   </td></tr>            
+            </table>
+  </tr>
+  {/if}
+  {* Hack Relations between modules *}
   </table>
  </td></tr>
 </table>
@@ -190,5 +229,53 @@
 {else}
 ModuleBuilder.helpSetup('studioWizard','relationshipHelp');
 {/if}
+{* Hack Relations between modules *}
+{literal}
+    
+ function lock_multiple_select(id, side){
+  if(!document.getElementById(id)){return false;}
 
+  if(side == 'lhs'){
+   lock_field = (id == 'lhs_signle_select') ? 'lhs_multiple_select' : 'lhs_signle_select';
+  }
+  else{
+   lock_field = (id == 'rhs_signle_select') ? 'rhs_multiple_select' : 'rhs_signle_select';
+  }
+  if(document.getElementById(id).checked){
+   document.getElementById(lock_field).disabled = true;
+  }
+  else{
+   document.getElementById(lock_field).disabled = false;
+  }
+ }
+ function lock_create_option(id, side){
+  if(!document.getElementById(id)){return false;}
+  var lock_field_create="";
+  
+  if(side == 'lhs'){
+   lock_field_create = (id == 'lhs_quick_create') ? 'lhs_full_form_create' : 'lhs_quick_create';
+  }else {
+   lock_field_create = (id == 'rhs_quick_create') ? 'rhs_full_form_create' : 'rhs_quick_create';
+  }
+  
+  if(document.getElementById(id).checked){
+   document.getElementById(lock_field_create).disabled = true;
+  }else{
+   document.getElementById(lock_field_create).disabled = false;
+  }
+ }
+ YAHOO.util.Event.onDOMReady(function(){
+  lock_multiple_select('lhs_signle_select', 'lhs');
+  lock_multiple_select('lhs_multiple_select', 'lhs');
+  lock_multiple_select('rhs_signle_select', 'rhs');
+  lock_multiple_select('rhs_multiple_select', 'rhs');
+  
+  lock_create_option('lhs_quick_create', 'lhs');
+  lock_create_option('lhs_full_form_create', 'lhs');
+  lock_create_option('rhs_quick_create', 'rhs');
+  lock_create_option('rhs_full_form_create', 'rhs');
+ });
+{/literal}
+
+{* Hack Relations between modules *}
 </script>
Index: modules/ModuleBuilder/views/view.relationship.php
===================================================================
--- modules/ModuleBuilder/views/view.relationship.php (revision 1)
+++ modules/ModuleBuilder/views/view.relationship.php (working copy)
@@ -193,7 +193,10 @@
         $this->smarty->assign ( 'cardinality', array_keys ( $cardinality ) ) ;
         $this->smarty->assign ( 'translated_cardinality', $cardinality ) ;
         $this->smarty->assign ( 'selected_cardinality', translate ( $relationship->getType () ) ) ;
-        
+        //Hack Relations between modules
+  $ckBoxOption = explode('_@@_', $relationship->ext1);
+        $this->smarty->assign ( 'ckBoxOption', $ckBoxOption ) ;
+  //Hack Relations between modules
         $relatable = array ( ) ;
         foreach ( $relatableModules as $name => $dummy )
         {

You can download the diff file and the modified core files here MB-RelationshipButtons.zip

The directory modified_files contains the original sugarcrm files with this patch applied for those users that are not yet familiar with SVN.

You are however recommended to use the diff files since you that way have 100% say over what code gets included in your code base rather than trusting the code blindly.
(This is not for these files in particular but goes in general on the internet)

No liability ... normal disclaimer goes here.


Post a Comment