How can one change the order on each subpanel either by code or through the GUI?
In Sugar 6 the user could change the order simply by dragging and dropping the subpanels under each module.
From what I can see this is not possible in 7.x.
I have tried to change
'order' => 1
in
custom/Extension/modules/Opportunities/Ext/Layoutdefs/some_file.php
with no luck at all..
UPDATE:
As UTAlan stated,
this will become part of the stock functionality of Sugar starting in version 7.5.0: https://web.sugarcrm.com/support/issues/66590
Until then, here is the reason and the solution:
The 'order' => 1, does not seem to work on Sugar 7 at the moment.
Solution
Copy the file
modules/Opportunities/clients/base/layouts/subpanels/subpanels.php
to
custom/modules/Opportunities/clients/base/layouts/subpanels/subpanels.php
Now, add your custom subpanel definition to the beginning of the array or in any order you desire.
My example looks like this now:
$viewdefs['Opportunities']['base']['layout']['subpanels'] = array(
'components' => array(
// This is my custom module
array(
'layout' => 'subpanel',
'label' => 'LBL_OPPORTUNITIES_FOOBAR_TITLE',
'context' => array(
'link' => 'opportunities_foobar_1',
),
),
.. // Code ommited
array(
'layout' => 'subpanel',
'label' => 'LBL_EMAILS_SUBPANEL_TITLE',
'context' => array (
'link' => 'archived_emails',
),
),
),
'type' => 'subpanels',
'span' => 12,
);
Long Answer:
Why is 'order' => 1 not working anymore?
Inside include/MetaDataManager/MetaDataConverter.php:327:
public function toLegacySubpanelLayoutDefs(array $layoutDefs, SugarBean $bean) {
..
foreach ($layoutDefs as $order => $def) {
..
$return[$def['context']['link']] = array(
'order' => $order,
..
}
The order that is being rendered in the view is based on which order each bean-name is inserted inside the 'components'-key inside this file:
modules/Opportunities/clients/base/layouts/subpanels/subpanels.php
Core modules are hard-coded inside the subpanel file for Opportunities.
This will become part of the stock functionality of Sugar starting in version 7.5.0: https://web.sugarcrm.com/support/issues/66590
Related
I'm trying to add a new field to Admin Preferences - a textarea field with tinymce. I've added code to AdminPreferencesController.php:
$this->fields_options['contact'] = array(
'title' => $this->l('Contact'),
'icon' => 'icon-cogs',
'submit' => array('title' => $this->l('Save')),
);
$this->fields_options['contact']['fields']['PS_CONTACT_ADDITIONAL_INFO'] = array(
'type' => 'textarea',
'label' => $this->l('Short description'),
'name' => 'short_description',
'lang' => true,
'cols' => 60,
'rows' => 10,
'autoload_rte' => 'rte',
'col' => 6,
);
But tinymce doesnt' appear and when I'm using HTML tags after saving they disappear. Presta strips all HTML tags.
How to allow HTML tags on this field and enable tinymce?
It seems that you can't just add it in a regular way. But you can implement it in a next way.
First of all, use field type textareaLang instead of textarea and add a parameter 'validation' => 'isCleanHtml' to this field
$this->fields_options['contact']['fields']['PS_CONTACT_ADDITIONAL_INFO'] = array(
'type' => 'textareaLang',
'label' => $this->l('Short description'),
'name' => 'short_description',
'lang' => true,
'cols' => 60,
'rows' => 10,
'col' => 6,
'validation' => 'isCleanHtml'
);
Create your own script to initialize your editor. I created a script tinymce.init.js and put it to js/admin/ folder
$(document).ready(function(){
ad = ''; // this is defenition of the external plugin path. I didn't fint how it can impact on script if it's empty but by default it it the path to your admin folder
iso = iso_user;
var config = {
selector: '.textarea-autosize'
};
tinySetup(config);
});
Then include tinymce script and your own to this controller AdminPreferencesController.php
public function setMedia()
{
$this->context->controller->addJquery();
$this->context->controller->addJS(
array(
_PS_JS_DIR_.'admin/tinymce.init.js',
_PS_JS_DIR_.'tiny_mce/tiny_mce.js',
_PS_JS_DIR_.'admin/tinymce.inc.js'
)
);
parent::setMedia();
}
It should implement your requirements. But don't forget that now you should call your configuration field in multilingual scope. So, add a language id to Configuration::get() like
Configuration::get('PS_CONTACT_ADDITIONAL_INFO, $id_lang)
whenever you use it.
P.S. Bear in mind that the best solution for your goal is to create a simple module which will handle this. And far more, it is recommended way.
I want to filter list that does not have an invalid email and opt-out email in Leads and Contact module using SugarCRM 7 API.
I have added below email filter in arguments but does not work. How to email filter via SugarCRM 7.x rest API.
$filter_arguments = array(
"filter" => array(
array(
"assigned_user_id" => 1,
),
array(
"email1" => array(
array(
'opt_out' => array(
'$equals' => ''
)
)
)
),
),
);
$url = $base_url . "/Contacts/filter";
Thanks.
This much code will not help you please check this :
Reference Link 1
Reference Link 2
The following example will demonstrate how to add a predefined filter on the Accounts module to return all records with an account type of "Customer" and industry of "Other".
To create a predefined filter, create a display label extension in ./custom/Extension/modules/<module>/Ext/Language/. For this example, we will create:
./custom/Extension/modules/Accounts/Ext/Language/en_us.filterAccountByTypeAndIndustry.php
<?php
$mod_strings['LBL_FILTER_ACCOUNT_BY_TYPE_AND_INDUSTRY'] = 'Customer/Other Accounts';
Next, create a custom filter extension in ./custom/Extension/modules/<module>/Ext/clients/base/filters/basic/.
For this example, we will create:
./custom/Extension/modules/Accounts/Ext/clients/base/filters/basic/filterAccountByTypeAndIndustry.php
<?php
$viewdefs['Accounts']['base']['filter']['basic']['filters'][] = array(
'id' => 'filterAccountByTypeAndIndustry',
'name' => 'LBL_FILTER_ACCOUNT_BY_TYPE_AND_INDUSTRY',
'filter_definition' => array(
array(
'account_type' => array(
'$in' => array(
'Customer',
),
),
),
array(
'industry' => array(
'$in' => array(
'Other',
),
),
),
),
'editable' => false,
'is_template' => false,
);
You should notice that the editable and is_template options have been set to "false". If editable is not set to "false", the filter will not be displayed in the list view filter's list.
Finally, navigate to Admin > Repair and click "Quick Repair and Rebuild" to rebuild the extensions and make the predefined filter available for users.
Adding Initial Filters to Lookup Searches
To add initial filters to record lookups and type-ahead searches, define a filter template. This will allow you to filter results for users when looking up a parent related record. The following example will demonstrate how to add an initial filter for the Account lookup on the Contacts module. This initial filter will limit records to having an account type of "Customer" and a dynamically assigned user value determined by the contact's assigned user.
To add an initial filter to the Contacts record view, create a display label for the filter in ./custom/Extension/modules/<module>/Ext/Language/. For this example , we will create:
./custom/Extension/modules/Accounts/Ext/Language/en_us.filterAccountTemplate.php
<?php
$mod_strings['LBL_FILTER_ACCOUNT_TEMPLATE'] = 'Customer Accounts By A Dynamic User';
Next, create a custom template filter extension in ./custom/Extension/modules/<module>/Ext/clients/base/filters/basic/.
For this example, create:
./custom/Extension/modules/Accounts/Ext/clients/base/filters/basic/filterAccountTemplate.php
<?php
$viewdefs['Accounts']['base']['filter']['basic']['filters'][] = array(
'id' => 'filterAccountTemplate',
'name' => 'LBL_FILTER_ACCOUNT_TEMPLATE',
'filter_definition' => array(
array(
'account_type' => array(
'$in' => array(),
),
),
array(
'assigned_user_id' => ''
)
),
'editable' => true,
'is_template' => true,
);
As you can see, the filter_definition contains arrays for account_type and assigned_user_id. These filter definitions will receive their values from the contact record view's metadata. You should also note that this filter has is_template and editable set to "true". This is required for initial filters.
Once the filter template is in place, modify the contact record view's metadata. To accomplish this, edit ./custom/modules/Contacts/clients/base/views/record/record.php to adjust the account_name field. If this file does not exist in your local Sugar installation, navigate to Admin > Studio > Contacts > Layouts > Record View and click "Save & Deploy" to generate it. In this file, identify the panel_body array as shown below:
1 =>
array (
'name' => 'panel_body',
'label' => 'LBL_RECORD_BODY',
'columns' => 2,
'labelsOnTop' => true,
'placeholders' => true,
'newTab' => false,
'panelDefault' => 'expanded',
'fields' =>
array (
0 => 'title',
1 => 'phone_mobile',
2 => 'department',
3 => 'do_not_call',
4 => 'account_name',
5 => 'email',
),
),
Next, modify the account_name field to contain the initial filter parameters.
1 =>
array (
'name' => 'panel_body',
'label' => 'LBL_RECORD_BODY',
'columns' => 2,
'labelsOnTop' => true,
'placeholders' => true,
'newTab' => false,
'panelDefault' => 'expanded',
'fields' =>
array (
0 => 'title',
1 => 'phone_mobile',
2 => 'department',
3 => 'do_not_call',
4 => array (
//field name
'name' => 'account_name',
//the name of the filter template
'initial_filter' => 'filterAccountTemplate',
//the display label for users
'initial_filter_label' => 'LBL_FILTER_ACCOUNT_TEMPLATE',
//the hardcoded filters to pass to the templates filter definition
'filter_populate' => array(
'account_type' => array('Customer')
),
//the dynamic filters to pass to the templates filter definition
//please note the index of the array will be for the field the data is being pulled from
'filter_relate' => array(
//'field_to_pull_data_from' => 'field_to_populate_data_to'
'assigned_user_id' => 'assigned_user_id',
)
),
5 => 'email',
),
),
Finally, navigate to Admin > Repair and click "Quick Repair and Rebuild". This will rebuild the extensions and make the initial filter available for users when selecting a parent account for a contact.
Adding Initial Filters to Drawers from a Controller
When creating your own views, you may need to filter a drawer called from within your custom controller. Using an initial filter, as described in the Adding Initial Filters to Lookup Searches section, we can filter a drawer with predefined values by creating a filter object and populating the config.filter_populate property as shown below:
//create filter
var filterOptions = new app.utils.FilterOptions()
.config({
'initial_filter': 'filterAccountTemplate',
'initial_filter_label': 'LBL_FILTER_ACCOUNT_TEMPLATE',
'filter_populate': {
'account_type': ['Customer'],
'assigned_user_id': 'seed_sally_id'
}
})
.format();
//open drawer
app.drawer.open({
layout: 'selection-list',
context: {
module: 'Accounts',
filterOptions: filterOptions,
parent: this.context
}
});
To create a filtered drawer with dynamic values, create a filter object and populate the config.filter_relate property using the populateRelate method as shown below:
//record to filter related fields by
var contact = app.data.createBean('Contacts', {
'first_name': 'John',
'last_name': 'Smith',
'assigned_user_id': 'seed_sally_id'
});
//create filter
var filterOptions = new app.utils.FilterOptions()
.config({
'initial_filter': 'filterAccountTemplate',
'initial_filter_label': 'LBL_FILTER_ACCOUNT_TEMPLATE',
'filter_populate': {
'account_type': ['Customer'],
},
'filter_relate': {
'assigned_user_id': 'assigned_user_id'
}
})
.populateRelate(contact)
.format();
//open drawer
app.drawer.open({
layout: 'selection-list',
context: {
module: 'Accounts',
filterOptions: filterOptions,
parent: this.context
}
});
I am creating my own module and one of its requirement is to have it located in a certain menu. My problem is that the menu is generated using a plugin PyroStreams.
So first things first, I downloaded a copy of the sample module on the Github, then have it place in addons/default/modules/. I refreshed my PyroCMS Admin -> Add-ons -> Modules and see the sample module in there. As stated on the detail.php of this sample module
public function info()
{
return array(
'name' => array(
'en' => 'Test Modules'
),
'description' => array(
'en' => 'My custom module.'
),
'frontend' => FALSE,
'backend' => TRUE,
'menu' => 'content', // You can also place modules in their top level menu. For example try: 'menu' => 'Sample',
'sections' => array(
'items' => array(
'name' => 'Test', // These are translated from your language file
'uri' => 'admin/sample',
'shortcuts' => array(
'create' => array(
'name' => 'sample:create',
'uri' => 'admin/sample/create',
'class' => 'add'
)
)
)
)
);
}
It should appear on the Content menu which is correct. Now, I can't find anything on docs that states instructions on properly mapping the menu for custom modules, so out of initiative I tried to change the value for menu => "content" to menu => "Test Stream" but that didn't work. As shown in the screenshot below, that is where I wanted to place my custom module, under the menu "Test Stream". What am I missing?
Add this method to your detail.php file:
public function admin_menu(&$menu)
{
// Create main menu item
add_admin_menu_place('lang:module:title', 9); // 9 is the placement order of your menu item, it would be after profile
// Create sub-menu
$menu['lang:module:title']['lang:module:submeu1'] = 'admin/add';
$menu['lang:module:title']['lang:module:submeu2'] = 'admin/edit';
}
also set the 'menu'=> false, at your info() method.
I had asked a question here a while back about setting up database populated dropdowns for SugarCRM. I received a really good answer and, after more php studies and a dev instance running, I decided to give it a shot. The instructions I followed can be found here. After I run the repair and rebuild, I would expect to see the custom field in my Fields list under the module in studio, but have not been able to find it. The module is named Makers (a1_makers as a database table). For good orders sake, there were no errors when I repaired/rebuilt after saving the files. Per the instructions, I first created a php file with a custom function to query the database (custom/Extension/application/Ext/Utils/getMakers.php):
<?php
function getMakers() {
static $makers = null;
if (!$makers){
global $db;
$query = "SELECT id, name FROM a1_maker";
$result = $db->query($query, false);
$accounts = array();
$accounts[''] = '';
while (($row = $db->fetchByAssoc($result)) !=null) {
$accounts[$row['id']] = $row['name'];
}
}
return $makers;
}
?>
Then, I set 'function' field in Vardefs to point to the function (custom/Extension/modules/Maker/Ext/Vardefs/makers_template.php):
<?php
$dictionary['Maker']['fields']['list_of_makers'] = array (
'name' => 'list_of_makers',
'vname' => 'LBL_MKRLST'
'function' => 'getMakers',
'type' => 'enum',
'len' => '100',
'comment' => 'List of makers populated from the database',
);
?>
Unfortunately, there are no errors and the repair/rebuild runs fine. I am just unable to see the custom field when I go into studio. Can anyone please help point out what I may be doing wrong?
I would recommend checking existence of newly created field 'list_of_makers' in cache/modules/Maker/Makervardefs.php file. If new field definition exists in that file, try add 'studio' => 'visible' to custom/Extension/modules/Maker/Ext/Vardefs/makers_template.php to get something like this:
<?php
$dictionary['Maker']['fields']['list_of_makers'] = array (
'name' => 'list_of_makers',
'vname' => 'LBL_MKRLST'
'function' => 'getMakers',
'type' => 'enum',
'studio' => 'visible'
'len' => '100',
'comment' => 'List of makers populated from the database',
);
Try to edit your custom/modules/Maker/metadata/editviewdefs.php manually and insert field definition by hand in proper place if everything above won't work.
$dictionary['Maker']['fields']['list_of_makers'] = array (
'name' => 'list_of_makers',
'vname' => 'LBL_MKRLST'
'function' => 'getMakers',
'type' => 'enum',
'studio' => 'visible'
'len' => '100',
'comment' => 'List of makers populated from the database',
'studio' => array(
'listview' => true,
'detailview' => true,
'editview' => true
),
);
I have a table that's been created by a module. I need to include some of its fields into an existing view.
I tried using the table wizard module, but all it does is create a separate view for that table. I'd like to be able to choose fields from that table to be added into an existing view as additional fields, or through relationships or something like that. Is there a workaround to do what I'm trying to do?
Ah. Views. Took me a while as well. This answer is for Drupal 6 and in the abstract shows how to define fields as well as using a relationship to allow the fields to link to the node table.
Inside modulename.module, you want a function that goes:
function modulename_views_api() {
return array(
'api' => 2,
);
}
Then you want to make a file called modulename.views.inc and define a function like this:
function modulename_views_data() {
$data['modulename_table'] = array(
'table' => array(
'group' => 'ModuleName',
'title' => 'Module name title',
),
'join' => array(
// to join to node, we'll use a field in modulename_table called 'nid'
'node' => array(
'left_field' => 'nid',
'field' => 'nid',
),
),
);
// now we define the fields in the table like this
// check out modules/views/handlers to see more specific handlers
$data['modulename_table']['fieldname'] = array(
'title' => 'fieldname',
'help' => 'fieldname description',
'field' => array(
'handler' => 'views_handler_field',
),
);
$data['modulename_table']['nid'] = array(
'title' => 'related node',
'help' => 'the field that relates back to {node}',
// here we implement a relationship to nid
'relationship' => array(
'base' => 'node',
'field' => 'nid',
'handler' => 'views_handler_relationship',
'label' => 'modulename row node',
),
// this relationship can be turned on in views
);
return $data;
}
You can use hook_views_data to define your table in code. As long as you don't want views to do special manipulations, it's almost as simple as defining the table with the schema API.
Your other option is to use table wizard to expose the tables to the database and then use the migrate module to create the views. http://drupal.org/project/migrate
I have found that the Views Custom Field module lets me do just about anything I need as far as adding oddball fields to views .. maybe it'd help ..