BUG šŸ› or MISUNDERSTANDING with Select All and CUSTOM EntryPoint

Hello there :hugs:,
This is my first post here, Iā€™m not used to write english so I apologize in advance :slight_smile:

My SuiteCRM version is: 7.11.15

I was doing a ā€œMass Update/Bulk Actionā€ button for custom CVS export in Meetings List View.
I started seeing sugar_3.js (jssource/src_files/include/javascript/ā€¦) to understand better whatā€™s happening.

When I was finishing my tests I found an ā€œerrorā€, when I clicked the select all with a custom EntryPoint, my php wasnā€™t getting data.

My solution was modify sugar_3.js and change line:

sugarListView.prototype.check_entire_list = function (form, field, value, list_count) {
ā€¦
form.elements[i].checked = value;
form.elements[i].disabled = true;
ā€¦

for

sugarListView.prototype.check_entire_list = function (form, field, value, list_count) {
ā€¦
form.elements[i].click();
form.elements[i].disabled = true;
ā€¦

I donā€™t know if Iā€™m misunderstanding some concepts about building EntryPoints ā€¦

Here is my custom EntryPoint code:

if(!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point');

//Check form inputs
$array_meetings_id = array();
if( isset($_POST['uid']) ) {
    $uid = $_POST['uid'];
    $seperator = ",";
    if( strpos($uid, $seperator)===false ) { $array_meetings_id[] = $uid; } 
    else { $array_meetings_id = explode($seperator, $uid); }
}

// Obtain full name from list of contacts
function get_full_name_contact($contactIds) {
    $return_txt = "";
    for ($i=0; $i < count($contactIds); $i++) { 
        $contactBean = BeanFactory::getBean('Contacts',$contactIds[$i]);
        $return_txt .= " - ". $contactBean->first_name ." ". $contactBean->last_name;
    }
    return $return_txt;
}

// var to appended content
$csv_content = '';
// GET MEETING INFO
for ($j=0; $j < count($array_meetings_id); $j++) {

    $id_meeting = $array_meetings_id[$j];
    
    $meetingBean = BeanFactory::getBean('Meetings',$id_meeting);
    $meetingName = $meetingBean->name;
    
    // GET CONTACT INFO
    $meetingBean->load_relationship('contacts');
    $contactIds = $meetingBean->contacts->get();    
    $meetingContacts = get_full_name_contact($contactIds);    

    $meetingAccount = $meetingBean->parent_name;
    $meetingAssigned = $meetingBean->assigned_user_name;
    $meetingDate_start  = $meetingBean->date_start;
    $meetingDuration    = $meetingBean->duration_hours . "h " . $meetingBean->duration_minutes . "m";
    $meetingDescription = $meetingBean->description;
    $meetingData_entered = $meetingBean->date_entered;
    $meetingStatus = $meetingBean->status;
    
    
    $csv_content .= "\n".$id_meeting .';'. $meetingName .';'. $meetingContacts .';'. $meetingAccount .';'. $meetingAssigned .';'. $meetingDate_start .';'. $meetingDuration .';'. $meetingDescription .';'. $meetingData_entered .';'. $meetingStatus; 
    

}

// FILE OPTIONS
$file_name = 'mettings';
$pathCSV   = "tempFiles/".$file_name.".csv";

$file_header = "MeetingID;Meeting;Contact;Client;Assigned to;Date;Duration;Description;CreationDate;Status";
$filte_text  = $file_header . $csv_content;

if( isset($_POST['uid']) ) {

    // Gen CSV
    $file_meeting = fopen( $pathCSV, "w" ) or die("Unable to open file response!");
    fwrite($file_meeting, $filte_text);
    fclose($file_meeting);

    // Download CSV
    header('Content-Type: application/csv');
    header('Content-Disposition: attachment; filename='.$file_name.'.csv; charset=utf-8');
    header('Pragma: no-cache');
    header('Content-Length: ' . filesize($pathCSV));
    readfile($pathCSV);

    // Delete CSV from server
    unlink($pathCSV);
}

Iā€™m not sure if Iā€™m doing it right by changing that sugar_3.js file.
With that change in sugar_3.js my code works and the rest of SuiteCRM seems to work fine too.

What do you think?

Thx :innocent:

1 Like

@Randy1

Welcome to community!

You shouldnā€™t change file sugar_3.js. I donā€™t see problem in your custom EntryPoint code but you can see file modules/AOS_PDF_Templates/generatePdf.php for example.

What kind of error did you find?

Hi,

Idk if it really is a bug or maybe itā€™s something I donā€™t do to get data.

If I use that button to select all and then click my new Exportar CSV button, I get no data

**Maybe data is not coming from uid

I make click(); change on sugar_3.js because with that manner the item is add to uid post parameter.

Sorry, but I canā€™t post more than one img per reply

@Randy1
May be there is problem with button.
Do you use standard call as ā€œexportā€ button?

<a ... onclick="return sListView.send_form(true, 'Accounts', 'index.php?entryPoint=export','Please select at least 1 record to proceed.')"> ... </a>

Iā€™m creating the button througth MeetingsListViewSmarty.php. I didnā€™t see any other way

$script = "<a href='javascript:void(0)' class=\"parent-dropdown-action-handler\" id='export_listview_top' " .
        "onclick=\"return sListView.send_form(true, '{$_REQUEST['module']}', " .
        "'index.php?entryPoint=export', " .
        "'{$app_strings['LBL_LISTVIEW_NO_SELECTED']}')\">{$app_strings['LBL_EXPORT']}</a>" .
        "</li><li>" . // List item hack
        "<a href='javascript:void(0)' id='map_listview_top' " .
        " onclick=\"return sListView.send_form(true, 'jjwg_Maps', " .
        "'index.php?entryPoint=jjwg_Maps&display_module={$_REQUEST['module']}', " .
        "'{$app_strings['LBL_LISTVIEW_NO_SELECTED']}')\">{$app_strings['LBL_MAP']}</a>".
        "</li><li>" . // List item hack
        "<a class='bulk-action' href='javascript:void(0)' id='ExportCSVMeetings'".
        "onclick=\"return sListView.send_form(true, '{$_REQUEST['module']}', " .
        "'index.php?entryPoint=ExportCSVMeetings', " .
        "'{$app_strings['LBL_LISTVIEW_NO_SELECTED']}')\"> Exportar CSV </a> ";

This is my custom part:

"</li><li>" . // List item hack
"<a class='bulk-action' href='javascript:void(0)' id='ExportCSVMeetings'".
"onclick=\"return sListView.send_form(true, '{$_REQUEST['module']}', " .
"'index.php?entryPoint=ExportCSVMeetings', " .
"'{$app_strings['LBL_LISTVIEW_NO_SELECTED']}')\"> Exportar CSV </a> ";

Sorry, I donā€™t see problem. Usually I write data into log file when I donā€™t find error. Try to add the code to your file of entryPoint:

$GLOBALS['log']->fatal(get_class()." ". __FUNCTION__." _REQUEST: ".print_r($_REQUEST,true));

I am not sure, but I seem to remember that this was always an issue - getting the data from the selected items in a list view only works in some cases. But I am not sure which ones. Itā€™s likely that the select ā€œallā€ doesnā€™t work.

Also, I am curious about this fix proposed here. Would this work with a huge number of records? It seems to handle them one by one, wouldnā€™t the JS hang if there were like 10000 records in the List view?

Hi @pgr,

Idk if itā€™s works with huge list of items I maintained the same code with minimal changes in sugar_3.js,
I see that when I make this sugar_3.js change selected items are not disabled which is the main diference I see.

If the sugar_3.js code of check_entire_list select that number of rows I guess that .click() will also do.
But I have the feeling that only check visible items ā€¦ I donĀ“t have such huge list to probe it ā€¦

Anyways @pgr if I select 10000 records I may end up with an error of max entries reached when Iā€™m generating CSV :face_with_hand_over_mouth:

I think that the correct way is execute this function sugarListView.prototype.check_all.check_item(form.elements[i], document.MassUpdate),
more than click(); whose purpouse is to execute that other funct.

I guess for now itā€™s enough to test with more than one page of records, and see how these three things work:

  • selecting some random records manually
  • using ā€œselect pageā€ from the menu
  • using ā€œselect allā€ from the menu

About your code performance, I think itā€™s perfectly acceptable that you simply donā€™t add a performance problemā€¦ but you can keep the performance problem that is already there :stuck_out_tongue:

Hi @pgr and @p.konetskiy, I was testing these things

  • selecting some random records manually
  • using ā€œselect pageā€ from the menu
  • using ā€œselect allā€ from the menu

with sugar_3.js changes and I got some errors when selecting all and so on, thats why .click() change row status instead of setting as selected. I restore sugar_3.js and use:

$GLOBALS['log']->fatal(get_class()." ". __FUNCTION__." _REQUEST: ".print_r($_REQUEST,true));

To get this on logs:

Iā€™m assuming that if I get current_post I will get_full_list
So I make this change on my custom entry point:

//Check form inputs
    $array_meetings_id = array();
    if( isset($_POST['uid']) ) {    
        $uid = $_POST['uid'];
        $seperator = ",";
        if( strpos($uid, $seperator)===false ) { $array_meetings_id[] = $uid; } 
        else { $array_meetings_id = explode($seperator, $uid); }
    } else if ( isset($_POST['current_post']) ) {
       $meetingBean = BeanFactory::getBean('Meetings');
        $beanList = $meetingBean->get_full_list();
        for ( $k=0; $k < count($beanList); $k++){
            array_push($array_meetings_id, $beanList[$k]->id);
        }
    }

else if is the new part, with this changes Iā€™m getting the correct output.

$GLOBALS['log']->fatal(get_class()." ". __FUNCTION__." _REQUEST: ".print_r($_REQUEST,true));

This is gold :1st_place_medal:
But in your docs, this is the recommended way to log: https://docs.suitecrm.com/developer/logging/

1 Like

@Randy1
Sorry. I didnā€™t give you correct file as example. I was should write this link:
modules/AOS_PDF_Templates/generatePdf.php

I ran into this problem before,
First add the button as follows, in my view.list.php

function preDisplay() {
		
		parent::preDisplay();

		$this->lv->actionsMenuExtraItems[1]=
                  '<a class=menuItem id=ACTION_BUTTON
                      onclick="document.MassUpdate.action.value=\'ACTION_BUTTON\';  
                      document.MassUpdate.submit();"
                      >ACTION_BUTTON
                  </a>';
    }

ACTION_BUTTON references the ACTION_BUTTON.php file in the same moduleā€¦
If in this you make a print of the $_Request of the screen, you get:

Array
(
    [return_action] => index
    [return_module] => module
    [massupdate] => true
    [delete] => false
    [merge] => false
    [current_query_by_page] =>  ...
    [module] => module
    [action] => action
    [lvso] => asc
    [module2_module_ORDER_BY] => 
    [uid] => 
    [select_entire_list] => 0
    [module2_module_offset] => 0
    [show_plus] => 
    [selectCount] => Array
        (
            [0] => 13
            [1] => 13
        )

    [assigned_user_name] => 
    [assigned_user_id] => 
    [accounts_module_1_name] => 
    [accounts_module_1accounts_ida] => 
    [mass] => Array
        (
            [0] => 6b3bc94a-f0b4-c33b-14f8-643ef41525ac
            [1] => 31430570-7c7a-bad2-341f-643ee57ecee7  // 2 selected records
        )
)

The difference when you do select all, is that the [select_entire_list] attribute is 1 ([select_entire_list] => 1)

Soā€¦ What I did was, that when this condition occurs, I call a SELECT * FROM of all the records, with deleted = 0

EDIT
Something that I forgot to mention is thatā€¦ the SELECT will not respect the filters that you make in the list viewā€¦ but maybe they can be sent by the $_REQUEST and added in the WHERE of the query