SugarCRM Adding Additional Details Info icon in Detail View - sugarcrm

in SugarCRM some modules like "Calls" has an "i" (Additional Details) icon in List view which shows some additional details about that record.
I want to display same kind for other modules like customer visits with some custom details of the records.
Any hints or guidance will be helpful.

1) Create a file in your metadata folder {MODULENAME}/metadata/additionalDetails.php. You have to find correct place of your module.
custom/modules/MODULENAME/metadata/
custom/modulebuilder/packages/PACKAGENAME/modules/MODULENAME/metadata/
etc...
2) and create a function something like this. replace {MODULENAME} and {MODULE_BEAN_NAME} with actual module name in all places.
function additionalDetails{MODULE_BEAN_NAME}($fields) {
static $mod_strings;
if(empty($mod_strings)) {
global $current_language;
$mod_strings = return_module_language($current_language, '{MODULENAME}');
}
$overlib_string = '';
if(!empty($fields['NAME']))
$overlib_string .= '<b>'. $mod_strings['LBL_NAME'] . '</b> ' . $fields['NAME'] . ' <br>';
//Add whatever info you want to show up to $overlib_string
$editLink = "index.php?action=EditView&module={MODULENAME}&record={$fields['ID']}";
$viewLink = "index.php?action=DetailView&module={MODULENAME}&record={$fields['ID']}";
return array(
'fieldToAddTo' => 'NAME',
'string' => $overlib_string,
'editLink' => $editLink,
'viewLink' => $viewLink
);
}
you have to create $overlib_string with your data (in html). If you need edit and view links on your modal box you have to return them as well. $fields is an associative array that contains db record.
3) The i icon should appear on the module list view.

Related

MailChimp Campaign Content Update

MailChimp campaign content docs - https://developer.mailchimp.com/documentation/mailchimp/reference/campaigns/content
I'm trying to replace some placeholders in a campaign content with actual values via the API. At first, I thought there might be some syntax errors or internal logic errors like non-unique mc:edits into a mc:repeatable that would get the HTML refused/declined by MailChimp, hence the update not taking place, however, that was not the case.
Tried replacing html with a simple <p>test</p> and it was still not working.
Here are a couple of local logs, I'll use xyz as my campaign id:
2018-02-26 16:26:13 [::1][9804][-][warning][application] calling GET /campaigns/xyz/content []
2018-02-26 16:26:13 [::1][9804][-][warning][application] got both plain_text and html versions of content
2018-02-26 16:26:13 [::1][9804][-][warning][application] calling PUT /campaigns/xyz/content {"html":"<p>test</p>"}
2018-02-26 16:26:14 [::1][9804][-][warning][application] got response [
'plain_text' => 'test' + other MailChimp stuff such as footer, that were appended automatically by MailChimp,
'html' => '<p>test</p>'
]
// calling GET immediately after PUT in order to see if any update occurred
2018-02-26 16:26:14 [::1][9804][-][warning][application] calling GET /campaigns/xyz/content []
2018-02-26 16:26:14 [::1][9804][-][warning][application] got updated html (my "test" paragraph + auto footer from MailChimp) and proper plain_text
Everything looks fine according to these, that means both versions updated as they were supposed to. However, on the next API/MailChimp dashboard request, it displays the old HTML content, preserving the update I've just made in the plain text version only.
No errors, nothing to look into. It could be any internal MailChimp behaviour.
PS: I know about Setting Mailchimp campaign content html not working or MailChimp API v3 campaign content template sections, but none of the answers provided to those are helpful.
PS2: I know I should contact MailChimp, but according to
Our MailChimp Support Team isn't trained at in-depth API troubleshooting. If you need a developer to help you configure something using the API, check out our great Experts Directory, which lists third-party MailChimp experts who can be hired to help out.
they don't provide support for API troubleshooting.
MailChimp doesn't allow updating the campaign's HTML content because the campaign type is based on a template.
In order to update the HTML content, the campaign has to be set to custom HTML instead of a template. You can check the type by sending a GET API request to /campaigns or /campaigns/{campaign_id} and finding the content_type attribute in the response (documentation).
Alternatively, in the dashboard, the type can be determined by editing the design of the email. Anything under 'Code your own' is HTML and templates are of course templates.
I'm not entirely sure why the first response to a PUT request on a template campaign shows the updated content, but changing the content type should let you update as you want to.
Hope this helps!
If anyone's still looking for an answer to this.
I managed to solve the issue several weeks ago without creating the campaign via API, but actually updating it.
I used placeholders like [product_card id=123], 3 cards per block/row, all repeatable, which are wrapped in a class that I named product-card. In the MailChimp dashboard, you may still see the placeholders, but on preview and any form of preview like thumbnail, it will display correctly.
On the server, I crawl through the campaign's content, "detect" section names based on how they seemed to me in MailChimp and update each section with the content that I want.
PHP snippet below, some Yii2 stuff, but mostly plain PHP. I use $preview to display a preview of how the template would look, I know it's not visible in the function.
/**
* #param $id - Id of the campaign
* #param $s - Whether to save or just preview
*
* #return bool
*/
function changeContent($id, $s = false)
{
$mcCampaign = new McCampaign();
$mcCampaign::$itemId = $id;
$content = $this->api->get("/campaigns/{$id}/content");
if (!isset($content['html'])) return false;
$template = $content['html'];
$forgedDom = new \DOMDocument();
$forgedDom->loadHTML($template);
$mcSections = [];
$finder = new \DOMXPath($forgedDom);
$nodes = $finder->query('//td[contains(#class, "product-card")]');
// disabling this shit in order to avoid strict errors
libxml_use_internal_errors(true);
$mcEditId = 1;
$mcEditIndex = 0;
foreach ($nodes as $key => $node) {
/** #var \DOMElement $node */
$textContent = $node->textContent;
if (!preg_match("#\[product_card id=\d+\]#", $textContent)) continue;
$productId = filter_var($textContent, FILTER_SANITIZE_NUMBER_INT);
$node->textContent = false;
$product = Product::findOne($productId);
$productDetails = $product ? $this->renderPartial('/partials/_mc-product', [
'product' => $product
]) : 'Product not found.';
if ($key != 0) {
if ($key % 3 == 0) {
$mcEditId = 1;
$mcEditIndex++;
} else {
$mcEditId++;
}
}
$mcSections["repeat_1:{$mcEditIndex}:product_card_{$mcEditId}"] = $productDetails;
$fragment = $forgedDom->createDocumentFragment();
$fragment->appendXML($productDetails);
$node->appendChild($fragment);
}
libxml_use_internal_errors(false);
$preview = $forgedDom->saveHTML();
// just in case
/* $preview = str_replace(["\n", "\t", "\r"], "", $preview); */
if ($s) {
if (!empty($mcSections)) {
$res = $this->api->put("/campaigns/{$id}/content", [
'template' => [
'id' => *template_id_here*,
'sections' => $mcSections
],
]);
// forcing Mc to rebuild cache
$this->api->get("/campaigns/{$id}/content");
Yii::$app->session->setFlash('success', 'Done.');
return $this->redirect(['campaign/index']);
} else {
Yii::$app->session->setFlash('error', 'Something went wrong.');
}
}
}

How can I implement star ratings using CakePHP?

i have find a plugin to implement star ratings using CakePHP https://github.com/CakeDC/ratings
but i don't know how to use it. i want to have five stars.
i'm a beginner in the CakePHP. and I would to calculate for the ratings.
i use cakphp 2.8.
should i create a table named rating ?
how do I calculate for the ratings ?
what should i write in the controller, view and model ?
plz help me
Thank you in advance for your answers.
Cordially.
First add this component in your controller like this
public $helpers = array('Ratings.RatingHelper');
public $components = array(
'Ratings.Ratings'
);
In your view function
$this->set('isRated', $this->{$this->modelClass}->isRatedBy($id, $this->Auth->user('id')));
In view.ctp file
if ($isRated === false) {
echo $this->Rating->display(array(
'item' => $post['Post']['id'],
'url' => array($post['Post']['id'])
));
} else {
echo __('You have already rated.');
}
You can check tutorial file in its docs folder. If have any issue plz let me know

Customizing layout to sfWidgetFormDoctrineChoice

I am using Symfony 1.4 sfWidgetFormDoctrineChoice
I have added the checkboxes to the form, which pulls the Model data successfully. What I want to do is also include a thumbnail next to the checkbox, along with the title.
$this->setWidget('bulkUploadVideos', new sfWidgetFormDoctrineChoice(array(
'model' => 'MediaAsset',
'query' => Doctrine_Query::create()->select('u.url')->from('MediaAsset u')->orderBy('id DESC'),
'add_empty' => false,
'multiple' => true,
'expanded' => true
)
));
This does a fantastic job of pulling the query into a list of checkboxes arranged like so:
⧠ Greenjeans
⧠ Mr Magoo
⧠ Droopy
In the Media Assets table, I also have an image url that I want to include in the layout. SO it would look like this:
|-img thumbnial- | ⧠ Greenjeans
|-img thumbnail- | ⧠ Mr. Magoo
|-img thumbnial- | ⧠ Droopy
I thought maybe using a formatter class, but I do not see any change in the form.
lib/form/formatters/sfWidgetFormSchemaFormatterAllVideos.class.php
<?php
class sfWidgetFormSchemaFormatterAllVideos extends sfWidgetFormSchemaFormatter {
protected
$rowFormat = "<span class=\"my-label-class\">%label%</span>\n <span>%error%%field%%help%%hidden_fields%</span>`n",
$errorRowFormat = "<span class=\"my-error-class\" colspan=\"2\">\n%errors%</span>\n",
$helpFormat = '<br />%help%',
$decoratorFormat = "<div class='custom-video-layout'>\n %content%</div>";
}
and then i put this at the bottom of my MediaAssetsForm.class.php
public function configure() {
parent::configure();
...
..
...
$this->getWidgetSchema()->setFormFormatterName('AllVideos');
Alas, the page layout looks exactly the same. Am I incorrectly calling the Formatter, or is there a much easier way of doing this?
Which btw, still does not answer the question of how I query the image url from the table into the output for each checkbox. That's the main problem I would like to solve. Thumbnails of each record in the form.
The formatter is used to render the whole form, what you need is to change the rendering of one of the widgets.
The sfwidgetFormDoctrineChoice has an option renderer which takes a formatter as an argument. The one that you need is the sfWidgetFormSelectCheckbox. What I would do is:
create your own class which will extend the sfWidgetFormSelectCheckbox class. E.g.
class sfWidgetFormMySelectWithThumbs extends sfWidgetFormSelectCheckbox {
}
Extend the configure function so it takes another option which will hold an array of your thumbnails.
public function configure($options = array(), $arguments = array()) {
parent::configure($options, $arguments);
$this->addOption('thumbnails', array());
}
Change the formatChoices function so it adds the image in front of the checkbox (you can copy and modify the original formatChoices function).
...
$sources = $this->getOption('thumbnails');
...
$inputs[$id] = array(
'input' => sprintf('| %s | %s',
$this->renderTag('img', array('src' => $sources[$key])),
$this->renderTag('input', array_merge($baseAttributes, $attributes))
),
'label' => $this->renderContentTag('label', self::escapeOnce($option), array('for' => $id)),
);
Use the formatter class in your widget:
$this->setWidget('bulkUploadVideos', new sfWidgetFormDoctrineChoice(array(
...
'renderer' => new sfWidgetFormMySelectWithThumbs(array('thumbnails' => $thumbanils))
)
));
Of course you need to retrieve the list of thumbnails as an array where the array keys are the same as the id's used for values for the checkboxes, but that shouldn't be an issue.

How to populate zend form field using session?

I am using sessions to populate a multi select box with options in my Zend application.
The user selects one or more options and fills in other fields on the form and then submits. If the user didn't select all of the options in the multi select then the form is displayed again but the multi select only has the options that the user did not select the last time. This process goes on until there are no more options from the multi select left to process.
Here is the code I use to get rid of the options that have already been processed so that they are not used to populate the multi select box:
if($form_successful){
// TODO remove $post['keyword_names'] (i.e. already processed) from $keyword_names (that come from $_SESSION)
$keyword_names = array_diff($keyword_names, $post['keyword_names']);
print_r($keyword_names);
if(is_array($keyword_names) && !empty($keyword_names)){
// save updated $keyword_names into $_SESSION['workflow1']
$session = new Zend_Session_Namespace('workflow1');
$session->keyword_names = $keyword_names;
// set flag to false so that we display form again
$form_successful = false;
}else{ // all keywords have been assigned
// go to next step
$this->_redirect('/workflow-1/step-'.($step+1).'/');
}
}
print_r($keyword_names); displays the correct options, however when the form is loaded when the user submits, the multi select displays the options that were there from the begining ie the options the user has just selected and submitted are not being taken out of the multi select, it is only when the user submits the form again then the multi select box updates.
Appreciate the help.
Solved the issue by making use of URL parameters. Here is the code (might differ a lot from what I posted first because some big changes were made):
// after successful form submission
if($form_successful){
// remove $post['keyword_names'] (i.e. already processed) from $keyword_names (that come from $_SESSION)
$keyword_names = array_diff($keyword_names, $post['keyword_names']);
// save remaining $keyword_names into $_SESSION['workflow1']
$session = new Zend_Session_Namespace('workflow1');
$session->keyword_names = $keyword_names;
if(is_array($keyword_names) && !empty($keyword_names)){
// redirect to the same step again - to ensure that the form will reflect (in select lists) newly created AdGroup and/or Campaign
// GET parameteres ($params_array) provide a way to remember user's choice
$params_array = array();
if(!empty($post['match_type_id'])){
$params_array['match_type_id'] = $post['match_type_id'];
}
if(!empty($post['with_permutations'])){
$params_array['with_permutations'] = $post['with_permutations'];
}
if(!empty($ad_group_id)){
$params_array['ad_group_id'] = $ad_group_id;
}
$this_step_url = UrlUtils::assemble('', $this->getRequest()->getActionName(), $this->getRequest()->getControllerName(), $this->getRequest()->getModuleName(), $params_array);
$this->_redirect($this_step_url);
}else{ // all keywords have been assigned
// go to next step
$this->_redirect('/workflow-1/step-'.($step+1).'/');
}
}
So you don't have any code about Zend_Form object here. How do you populate the form element? If you post your class code which extends Zend_Form (or any other code dials with your form) then I may help. But in any case you can populate your multiselectbox with setMultiOptions() method or addMultiOption() for each item in multiselectbox.

KRL and Yahoo Local Search

I'm trying to use Yahoo Local Search in a Kynetx Application.
ruleset avogadro {
meta {
name "yahoo-local-ruleset"
description "use results from Yahoo local search"
author "randall bohn"
key yahoo_local "get-your-own-key"
}
dispatch { domain "example.com"}
global {
datasource local:XML <- "http://local.yahooapis.com/LocalSearchService/V3/localsearch";
}
rule add_list {
select when pageview ".*" setting ()
pre {
ds = datasource:local("?appid=#{keys:yahoo_local()}&query=pizza&zip=#{zip}&results=5");
rs = ds.pick("$..Result");
}
append("body","<ul id='my_list'></ul>");
always {
set ent:pizza rs;
}
}
rule add_results {
select when pageview ".*" setting ()
foreach ent:pizza setting pizza
pre {
title = pizza.pick("$..Title");
}
append("#my_list", "<li>#{title}</li>");
}
}
The list I wind up with is
. [object Object]
and 'title' has
{'$t' => 'Pizza Shop 1'}
I can't figure out how to get just the title. It looks like the 'text content' from the original XML file turns into {'$t' => 'text content'} and the '$t' give problems to pick().
When XML datasources and datasets get converted into JSON, the text value within an XML node gets assigned to $t. You can pick the text of the title by changing your pick statement in the pre block to
title = pizza.pick("$..Title.$t");
Try that and see if that solves your problem.
Side notes on things not related to your question to consider:
1) Thank you for sharing the entire ruleset, what problem you were seeing and what you expected. Made answering your question much easier.
2) The ruleset identifier should not be changed from what AppBuilder or the command-line gem generate for you. Your identifier that is currently
ruleset avogadro {
should look something more like
ruleset a60x304 {
3) You don't need the
setting ()
in the select statement unless you have a capture group in your regular expression
Turns out that pick("$..Title.$t") does work. It looks funny but it works. Less funny than a clown hat I guess.
name = pizza.pick("$..Title.$t");
city = pizza.pick("$..City.$t");
phone = pizza.pick("$..Phone.$t");
list_item = "<li>#{name}/#{city} #{phone}</li>"
Wish I had some pizza right now!