This posting is written based on the SugarCrm 5.5.2 codebase.
In SugarCRM you only get a link pointing to the detail view of a record on the Name column/field in a list view or a sub panel. To add support for link to detail view on a arbitrary fields/columns we need to make some changes to the Module Builder code.
Below you can find the Module Builder screen where you can define how the list view of a given module should look.
In SugarCRM you only get a link pointing to the detail view of a record on the Name column/field in a list view or a sub panel. To add support for link to detail view on a arbitrary fields/columns we need to make some changes to the Module Builder code.
Below you can find the Module Builder screen where you can define how the list view of a given module should look.
Now when we click on the Edit icon of “Test” field then it will show a following screen. (The link checkbox is a result of the changes we are going to make to the code)
When user check the Link checkbox and deploy the module then detail view hyperlink will be applied on Test field in ListView.
Likewise we can apply the hyperlink on the fields in the sub panel also. For that we need to modify the Available Subpanel layouts in Module Builder as shown in the screen shot below.
Please note that the code changes we are about to do are not upgrade safe. This means that you cannot just upgrade your SugarCrm installation when the next official release is available. If you do upgrade you will loose the ability to specify if a field in a list view or sub panel should have a link. The generated *defs.php files however should be upgrade safe meaning that if you have changed some fields to be a link this should still work on the new version.
There are several files that needs to be modified :
1. /modules/ModuleBuilder/javascript/studiotabgroups.js
winput.value = "width=" + document.getElementById(items[i].id+'width').innerHTML; form.appendChild(winput); //} //Hack Module Builder - Subpanel and ListView field support for hyperlink to detailsview var linput = document.createElement('input'); linput.type='hidden'; linput.name= input.value + 'link'; linput.value = "link=" + document.getElementById(items[i].id+'link').value; form.appendChild(linput); //Hack Module Builder - Subpanel and ListView field support for hyperlink to detailsview } }
2. /modules/ModuleBuilder/parsers/views/ListLayoutMetaDataParser.php
Following lines are added to add the 'link' => true in a listviewdefs.php file to have a hyperlink on the field.
Following lines are added to add the 'link' => true in a listviewdefs.php file to have a hyperlink on the field.
else { $newViewdefs [ $fieldname ] [ 'width' ] = "10%"; } //Hack Module Builder - Subpanel and ListView field support for hyperlink to detailsview $link = substr ( $_REQUEST [ $fieldname . 'link' ], 5, 5 ) ; if ((isset ( $link )) && ($link !='')) { $newViewdefs [ $fieldname ] [ 'link' ] = $link=='true'?true:false ; } else { $newViewdefs [ $fieldname ] [ 'link' ] = false ; } if($newViewdefs [ $fieldname ] [ 'link' ] == false ){ unset($newViewdefs [ $fieldname ] [ 'link' ]); } //Hack Module Builder - Subpanel and ListView field support for hyperlink to detailsview $newViewdefs [ $fieldname ] [ 'default' ] = ($i == 0) ; } }
3. /modules/ModuleBuilder/parsers/views/SubpanelMetaDataParser.php
In this file the _populateFromRequest function is rewritten to handle the Request after submit. In this function following lines are written to add a 'widget_class' => 'SubPanelDetailViewLink' in a layout file of the Subpanel.
} return $listDef; } //Hack Module Builder - Subpanel and ListView field support for hyperlink to detailsview /** * This will populate field defs from request * */ protected function _populateFromRequest () { $GLOBALS [ 'log' ]->debug ( get_class ( $this ) . "->populateFromRequest()" ) ; $GLOBALS [ 'log' ]->debug ( get_class ( $this ) . "->populateFromRequest() - fielddefs = ".print_r($this->_fielddefs, true)); // Transfer across any reserved fields, that is, any where studio !== true, which are not editable but must be preserved $newViewdefs = array ( ) ; foreach ( $this->_viewdefs as $key => $def ) { if (isset ( $def [ 'studio' ] ) && $def [ 'studio' ] !== true) $newViewdefs [ $key ] = $def ; } $rejectTypes = array ( 'html' , 'enum' , 'text' ) ; // only take items from group_0 for searchviews (basic_search or advanced_search) and subpanels (which both are missing the Available column) - take group_0, _1 and _2 for all other list views $lastGroup = (isset ( $this->columns [ 'LBL_AVAILABLE' ] )) ? 2 : 1 ; for ( $i = 0 ; isset ( $_POST [ 'group_' . $i ] ) && $i < $lastGroup ; $i ++ ) { foreach ( $_POST [ 'group_' . $i ] as $fieldname ) { $fieldname = strtolower ( $fieldname ) ; if (isset ( $this->_viewdefs [ $fieldname ] )) { $newViewdefs [ $fieldname ] = $this->_viewdefs [ $fieldname ] ; } else if (isset($this->originalViewDef) && isset ( $this->originalViewDef [ $fieldname ] )) { $newViewdefs [ $fieldname ] = $this->originalViewDef [ $fieldname ] ; } else { $newViewdefs [ $fieldname ] = array ( 'width' => 10 , $this->labelIdentifier => $this->_fielddefs [ $fieldname ] [ 'vname' ] ) ; } // sorting fields of certain types will cause a database engine problems if (isset ( $this->_fielddefs [ $fieldname ] ) && (isset($this->_fielddefs[$fieldname]['type']) && in_array ( $this->_fielddefs [ $fieldname ] [ 'type' ], $rejectTypes ))) { $newViewdefs [ $fieldname ] [ 'sortable' ] = false ; } // Bug 23728 - Make adding a currency type field default to setting the 'currency_format' to true if (isset ( $this->_fielddefs [ $fieldname ] [ 'type' ]) && $this->_fielddefs [ $fieldname ] [ 'type' ] == 'currency') { $newViewdefs [ $fieldname ] [ 'currency_format' ] = true; } if (isset ( $_REQUEST [ strtolower ( $fieldname ) . 'width' ] )) { $width = substr ( $_REQUEST [ $fieldname . 'width' ], 6, 3 ) ; if (strpos ( $width, "%" ) != false) { $width = substr ( $width, 0, 2 ) ; } if ($width < 101 && $width > 0) { $newViewdefs [ $fieldname ] [ 'width' ] = $width."%" ; } } else if (isset ( $this->_viewdefs [ $fieldname ] [ 'width' ] )) { $newViewdefs [ $fieldname ] [ 'width' ] = $this->_viewdefs [ $fieldname ] [ 'width' ] ; } //Hack Module Builder - Subpanel and ListView field support for hyperlink to detailsview /** * Following code is written to apply the SubPanelDetailViewLink widget to those fileds for which thee * Link checkbox is checked. */ $link = substr ( $_REQUEST [ $fieldname . 'link' ], 5, 5 ) ; if ((isset ( $link )) && ($link !='')) { if($link=='true'){ $newViewdefs [ $fieldname ] [ 'widget_class' ] = 'SubPanelDetailViewLink' ; } else { $newViewdefs [$fieldname]['widget_class'] = false ; } } else { $newViewdefs [ $fieldname ] [ 'widget_class' ] = false ; } if( (isset($this->_viewdefs[$fieldname]['widget_class'])) && ($this->_viewdefs[$fieldname]['widget_class'] != '' && $this->_viewdefs[$fieldname]['widget_class'] != 'SubPanelDetailViewLink') ){ $newViewdefs [ $fieldname ] ['widget_class'] = $this->_viewdefs[$fieldname]['widget_class']; } if($newViewdefs[$fieldname]['widget_class'] == false){ unset($newViewdefs[$fieldname]['widget_class']); } //Hack Module Builder - Subpanel and ListView field support for hyperlink to detailsview $newViewdefs [ $fieldname ] [ 'default' ] = ($i == 0) ; } } $this->_viewdefs = $newViewdefs ; } } ?>
4. /modules/ModuleBuilder/tpls/editProperty.tpl
Following lines are added to store the value of the Link field.
var property = field.name.substring('editProperty_'.length); var id = field.id.substring('editProperty_'.length); document.getElementById(id).innerHTML = field.value; //Hack Module Builder - Subpanel and ListView field support for hyperlink to detailsview if(id.substr( -4) == 'link'){ document.getElementById(id).value = field.value; } //Hack Module Builder - Subpanel and ListView field support for hyperlink to detailsview } } }
Link checkbox is added in following lines (please note that the syntax highlighting does not work properly for the Smarty template - that is a project for another blog posting I guess).
{if isset($property.hidden)} {$property.value} {else} {if $property.name eq "Link"} <input onchange='document.getElementById("editProperty_{$id}{$property.id}").value = this.checked;' value='{$property.value}' type='checkbox' {if ($property.value eq "true")}checked{/if}> {else} <input onchange='document.getElementById("editProperty_{$id}{$property.id}").value = this.value' value='{$property.value}'> {/if} {/if} </td> </tr>
5. /modules/ModuleBuilder/tpls/listView.tpl
Following lines are added to pass the value of the Link field when user click on the Edit icon and to create a hidden field which will store a Link field’s value
(please note that the syntax highlighting does not work properly for the Smarty template - that is a project for another blog posting I guess)
<td></td> <td align="right"> <img src="{sugar_getimagepath file='edit_inline.gif'}" style="cursor: pointer;" {* Following lines are added to pass the value of the Link field when user click on the Edit icon *} onclick="var value_label = document.getElementById('subslot{$modCounter}label').innerHTML; var value_width = document.getElementById('subslot{$modCounter}width').innerHTML; var value_link = document.getElementById('subslot{$modCounter}link').value; ModuleBuilder.getContent('module=ModuleBuilder&action=editProperty&view_module={$view_module}{if isset($subpanel)}&subpanel={$subpanel}{/if}{if $MB}&MB={$MB}&view_package={$view_package}{/if}&id_label=subslot{$modCounter}label&name_label=label_{if isset($value.label)}{$value.label}{elseif !empty($value.vname)}{$value.vname}{else}{$key}{/if}&title_label={$MOD.LBL_LABEL_TITLE}&value_label=' + value_label + '&id_width=subslot{$modCounter}width&name_width={$MOD.LBL_WIDTH}&value_width=' + value_width+'&name_link=Link&id_link=subslot{$modCounter}link&value_link=' + value_link );"> {* Following lines are added to pass the value of the Link field when user click on the Edit icon *} </td> </tr> <tr class='fieldValue'> {if empty($hideKeys)}<td>[{$key}]</td>{/if} <td align="right" colspan="2"><span id='subslot{$modCounter}width'>{$value.width}</span><span>%</span></td> {* Following lines are added to create a hidden field which will store a Link field’s value *} <input type='hidden' id='subslot{$modCounter}link' value='{if !empty($subpanel) }{if ($value.widget_class eq "SubPanelDetailViewLink")}true{else}false{/if}{else}{if ($value.link)}true{else}false{/if}{/if}' /> {* Following lines are added to create a hidden field which will store a Link field’s value *} </tr> </table> </li>
6. /modules/ModuleBuilder/views/view.listview.php
$groups [ $groupKey ] [ $fieldKey ] [ 'width' ] = substr ( $field [ 'width' ], 0, strlen ( $field [ 'width' ] ) - 1 ) ; } } //Hack Module Builder - Subpanel and ListView field support for hyperlink to detailsview $groups [ $groupKey ] [ $fieldKey ] [ 'link' ] = $field [ 'link' ]; //Hack Module Builder - Subpanel and ListView field support for hyperlink to detailsview } }
And finally we have the changes in a SVN diff/patch format
Index: modules/ModuleBuilder/javascript/studiotabgroups.js =================================================================== --- modules/ModuleBuilder/javascript/studiotabgroups.js (revision 11) +++ modules/ModuleBuilder/javascript/studiotabgroups.js (working copy) @@ -108,6 +108,13 @@ winput.value = "width=" + document.getElementById(items[i].id+'width').innerHTML; form.appendChild(winput); // } + //Hack Module Builder - Subpanel and ListView field support for hyperlink to detailsview + var linput = document.createElement('input'); + linput.type='hidden'; + linput.name= input.value + 'link'; + linput.value = "link=" + document.getElementById(items[i].id+'link').value; + form.appendChild(linput); + //Hack Module Builder - Subpanel and ListView field support for hyperlink to detailsview } } } Index: modules/ModuleBuilder/parsers/views/ListLayoutMetaDataParser.php =================================================================== --- modules/ModuleBuilder/parsers/views/ListLayoutMetaDataParser.php (revision 10) +++ modules/ModuleBuilder/parsers/views/ListLayoutMetaDataParser.php (working copy) @@ -300,7 +300,20 @@ else { $newViewdefs [ $fieldname ] [ 'width' ] = "10%"; } - + //Hack Module Builder - Subpanel and ListView field support for hyperlink to detailsview + $link = substr ( $_REQUEST [ $fieldname . 'link' ], 5, 5 ) ; + if ((isset ( $link )) && ($link !='')) + { + $newViewdefs [ $fieldname ] [ 'link' ] = $link=='true'?true:false ; + } else { + $newViewdefs [ $fieldname ] [ 'link' ] = false ; + } + + if($newViewdefs [ $fieldname ] [ 'link' ] == false ){ + unset($newViewdefs [ $fieldname ] [ 'link' ]); + } + + //Hack Module Builder - Subpanel and ListView field support for hyperlink to detailsview $newViewdefs [ $fieldname ] [ 'default' ] = ($i == 0) ; } } Index: modules/ModuleBuilder/parsers/views/SubpanelMetaDataParser.php =================================================================== --- modules/ModuleBuilder/parsers/views/SubpanelMetaDataParser.php (revision 7) +++ modules/ModuleBuilder/parsers/views/SubpanelMetaDataParser.php (working copy) @@ -156,6 +156,107 @@ } return $listDef; } + //Hack Module Builder - Subpanel and ListView field support for hyperlink to detailsview + /** + * This will populate field defs from request + * + */ + protected function _populateFromRequest () + { + $GLOBALS [ 'log' ]->debug ( get_class ( $this ) . "->populateFromRequest()" ) ; + $GLOBALS [ 'log' ]->debug ( get_class ( $this ) . "->populateFromRequest() - fielddefs = ".print_r($this->_fielddefs, true)); + + // Transfer across any reserved fields, that is, any where studio !== true, which are not editable but must be preserved + $newViewdefs = array ( ) ; + foreach ( $this->_viewdefs as $key => $def ) + { + if (isset ( $def [ 'studio' ] ) && $def [ 'studio' ] !== true) + $newViewdefs [ $key ] = $def ; + } + + $rejectTypes = array ( 'html' , 'enum' , 'text' ) ; + // only take items from group_0 for searchviews (basic_search or advanced_search) and subpanels (which both are missing the Available column) - take group_0, _1 and _2 for all other list views + $lastGroup = (isset ( $this->columns [ 'LBL_AVAILABLE' ] )) ? 2 : 1 ; + for ( $i = 0 ; isset ( $_POST [ 'group_' . $i ] ) && $i < $lastGroup ; $i ++ ) + { + foreach ( $_POST [ 'group_' . $i ] as $fieldname ) + { + $fieldname = strtolower ( $fieldname ) ; + + if (isset ( $this->_viewdefs [ $fieldname ] )) + { + $newViewdefs [ $fieldname ] = $this->_viewdefs [ $fieldname ] ; + } else if (isset($this->originalViewDef) && isset ( $this->originalViewDef [ $fieldname ] )) + { + $newViewdefs [ $fieldname ] = $this->originalViewDef [ $fieldname ] ; + } + else + { + $newViewdefs [ $fieldname ] = array ( 'width' => 10 , $this->labelIdentifier => $this->_fielddefs [ $fieldname ] [ 'vname' ] ) ; + } + // sorting fields of certain types will cause a database engine problems + if (isset ( $this->_fielddefs [ $fieldname ] ) && (isset($this->_fielddefs[$fieldname]['type']) + && in_array ( $this->_fielddefs [ $fieldname ] [ 'type' ], $rejectTypes ))) + { + $newViewdefs [ $fieldname ] [ 'sortable' ] = false ; + } + // Bug 23728 - Make adding a currency type field default to setting the 'currency_format' to true + if (isset ( $this->_fielddefs [ $fieldname ] [ 'type' ]) && $this->_fielddefs [ $fieldname ] [ 'type' ] == 'currency') + { + $newViewdefs [ $fieldname ] [ 'currency_format' ] = true; + } + + if (isset ( $_REQUEST [ strtolower ( $fieldname ) . 'width' ] )) + { + $width = substr ( $_REQUEST [ $fieldname . 'width' ], 6, 3 ) ; + if (strpos ( $width, "%" ) != false) + { + $width = substr ( $width, 0, 2 ) ; + } + if ($width < 101 && $width > 0) + { + $newViewdefs [ $fieldname ] [ 'width' ] = $width."%" ; + } + } else if (isset ( $this->_viewdefs [ $fieldname ] [ 'width' ] )) + { + $newViewdefs [ $fieldname ] [ 'width' ] = $this->_viewdefs [ $fieldname ] [ 'width' ] ; + } + + + //Hack Module Builder - Subpanel and ListView field support for hyperlink to detailsview + /** + * Following code is written to apply the SubPanelDetailViewLink widget to those fileds for which thee + * Link checkbox is checked. + */ + $link = substr ( $_REQUEST [ $fieldname . 'link' ], 5, 5 ) ; + if ((isset ( $link )) && ($link !='')) + { + if($link=='true'){ + $newViewdefs [ $fieldname ] [ 'widget_class' ] = 'SubPanelDetailViewLink' ; + } else { + $newViewdefs [$fieldname]['widget_class'] = false ; + } + } else { + $newViewdefs [ $fieldname ] [ 'widget_class' ] = false ; + } + + if( (isset($this->_viewdefs[$fieldname]['widget_class'])) && + ($this->_viewdefs[$fieldname]['widget_class'] != '' && + $this->_viewdefs[$fieldname]['widget_class'] != 'SubPanelDetailViewLink') ){ + $newViewdefs [ $fieldname ] ['widget_class'] = $this->_viewdefs[$fieldname]['widget_class']; + } + + if($newViewdefs[$fieldname]['widget_class'] == false){ + unset($newViewdefs[$fieldname]['widget_class']); + } + //Hack Module Builder - Subpanel and ListView field support for hyperlink to detailsview + + $newViewdefs [ $fieldname ] [ 'default' ] = ($i == 0) ; + } + } + $this->_viewdefs = $newViewdefs ; + } + } ?> Index: modules/ModuleBuilder/tpls/editProperty.tpl =================================================================== --- modules/ModuleBuilder/tpls/editProperty.tpl (revision 8) +++ modules/ModuleBuilder/tpls/editProperty.tpl (working copy) @@ -60,6 +60,11 @@ var property = field.name.substring('editProperty_'.length); var id = field.id.substring('editProperty_'.length); document.getElementById(id).innerHTML = field.value; + //Hack Module Builder - Subpanel and ListView field support for hyperlink to detailsview + if(id.substr( -4) == 'link'){ + document.getElementById(id).value = field.value; + } + //Hack Module Builder - Subpanel and ListView field support for hyperlink to detailsview } } } @@ -90,7 +95,11 @@ {if isset($property.hidden)} {$property.value} {else} + {if $property.name eq "Link"} + <input onchange='document.getElementById("editProperty_{$id}{$property.id}").value = this.checked;' value='{$property.value}' type='checkbox' {if ($property.value eq "true")}checked{/if}> + {else} <input onchange='document.getElementById("editProperty_{$id}{$property.id}").value = this.value' value='{$property.value}'> + {/if} {/if} </td> </tr> Index: modules/ModuleBuilder/tpls/listView.tpl =================================================================== --- modules/ModuleBuilder/tpls/listView.tpl (revision 7) +++ modules/ModuleBuilder/tpls/listView.tpl (working copy) @@ -93,12 +93,13 @@ <td></td> <td align="right"> <img src="{sugar_getimagepath file='edit_inline.gif'}" style="cursor: pointer;" - onclick="var value_label = document.getElementById('subslot{$modCounter}label').innerHTML; var value_width = document.getElementById('subslot{$modCounter}width').innerHTML; ModuleBuilder.getContent('module=ModuleBuilder&action=editProperty&view_module={$view_module}{if isset($subpanel)}&subpanel={$subpanel}{/if}{if $MB}&MB={$MB}&view_package={$view_package}{/if}&id_label=subslot{$modCounter}label&name_label=label_{if isset($value.label)}{$value.label}{elseif !empty($value.vname)}{$value.vname}{else}{$key}{/if}&title_label={$MOD.LBL_LABEL_TITLE}&value_label=' + value_label + '&id_width=subslot{$modCounter}width&name_width={$MOD.LBL_WIDTH}&value_width=' + value_width );"> + onclick="var value_label = document.getElementById('subslot{$modCounter}label').innerHTML; var value_width = document.getElementById('subslot{$modCounter}width').innerHTML; var value_link = document.getElementById('subslot{$modCounter}link').value; ModuleBuilder.getContent('module=ModuleBuilder&action=editProperty&view_module={$view_module}{if isset($subpanel)}&subpanel={$subpanel}{/if}{if $MB}&MB={$MB}&view_package={$view_package}{/if}&id_label=subslot{$modCounter}label&name_label=label_{if isset($value.label)}{$value.label}{elseif !empty($value.vname)}{$value.vname}{else}{$key}{/if}&title_label={$MOD.LBL_LABEL_TITLE}&value_label=' + value_label + '&id_width=subslot{$modCounter}width&name_width={$MOD.LBL_WIDTH}&value_width=' + value_width+'&name_link=Link&id_link=subslot{$modCounter}link&value_link=' + value_link );"> </td> </tr> <tr class='fieldValue'> {if empty($hideKeys)}<td>[{$key}]</td>{/if} <td align="right" colspan="2"><span id='subslot{$modCounter}width'>{$value.width}</span><span>%</span></td> + <input type='hidden' id='subslot{$modCounter}link' value='{if !empty($subpanel) }{if ($value.widget_class eq "SubPanelDetailViewLink")}true{else}false{/if}{else}{if ($value.link)}true{else}false{/if}{/if}' /> </tr> </table> </li> Index: modules/ModuleBuilder/views/view.listview.php =================================================================== --- modules/ModuleBuilder/views/view.listview.php (revision 9) +++ modules/ModuleBuilder/views/view.listview.php (working copy) @@ -206,6 +206,9 @@ $groups [ $groupKey ] [ $fieldKey ] [ 'width' ] = substr ( $field [ 'width' ], 0, strlen ( $field [ 'width' ] ) - 1 ) ; } } + //Hack Module Builder - Subpanel and ListView field support for hyperlink to detailsview + $groups [ $groupKey ] [ $fieldKey ] [ 'link' ] = $field [ 'link' ]; + //Hack Module Builder - Subpanel and ListView field support for hyperlink to detailsview } }
5 comments:
How would this be on 6.0 CE?
I have a plan to update these and a few more patches to SugarCrm 6.0 and hopefully get them in as part of the core package so I don't have to maintain them anymore. However I have been trying to get these and a lot of other patches in to the core base since 5.0.0b2 (beta2) and only very few have been included.
I will post a new posting on the forums and here when/if I get it ported to 6.0.
Have you been able to get the updated code for the newest sugar community version?
Hi Dominic
I have not been able to get this included in official SugarCrm CE edition.
I have plans for upgrading all our changes to the latest SugarCrm CE and then forking the project on github.
Unfortunately this is not a trivial undertaking and I find myself currently short for time, so it not something I can schedule for a specific date in the future.
Regards
Kenneth
Hi Kenneth,
I am also looking for a way to put links on fileds in Listview in Sugar CE 6.x
I am prepared to help you with forking and porting to github... if interested let me knov at jernejp at gmail
Best Regards,
Jernej
Post a Comment