From 47694b79fb01d68717f21288b59b9c740db31533 Mon Sep 17 00:00:00 2001
From: Ruben Estrada <rulotec1@gmail.com>
Date: Sat, 18 Jul 2020 22:12:34 -0500
Subject: [PATCH] fix #1349 and #1241 by adding deletion funcionality to mass
 edition. It adds checkboxes for each field in the mass edit layout, which
 allows delete fields by just checking the checkbox without modifying the
 field contents.

---
 layouts/v7/modules/Vtiger/MassEditForm.tpl    |  1 +
 .../Vtiger/partials/EditViewContents.tpl      |  3 +
 layouts/v7/modules/Vtiger/resources/List.js   | 57 +++++++++++++------
 modules/Vtiger/actions/MassSave.php           | 49 +++++++---------
 4 files changed, 64 insertions(+), 46 deletions(-)

diff --git a/layouts/v7/modules/Vtiger/MassEditForm.tpl b/layouts/v7/modules/Vtiger/MassEditForm.tpl
index 0a138c42e..17f24de82 100644
--- a/layouts/v7/modules/Vtiger/MassEditForm.tpl
+++ b/layouts/v7/modules/Vtiger/MassEditForm.tpl
@@ -10,6 +10,7 @@
  ********************************************************************************/
 -->*}
 {strip}
+{assign var="MASS_EDITION_MODE" value=true}
 <div id="massEditContainer" class='fc-overlay-modal modal-content'>
     <form class="form-horizontal" id="massEdit" name="MassEdit" method="post" action="index.php">
         <input type="hidden" name="module" value="{$MODULE}" />
diff --git a/layouts/v7/modules/Vtiger/partials/EditViewContents.tpl b/layouts/v7/modules/Vtiger/partials/EditViewContents.tpl
index 1db8f29b5..1134f02f6 100644
--- a/layouts/v7/modules/Vtiger/partials/EditViewContents.tpl
+++ b/layouts/v7/modules/Vtiger/partials/EditViewContents.tpl
@@ -46,6 +46,9 @@
 										{assign var=COUNTER value=$COUNTER+1}
 									{/if}
 									<td class="fieldLabel alignMiddle">
+										{if $MASS_EDITION_MODE}
+											<input class="inputElement" id="include_in_mass_edit_{$FIELD_MODEL->getFieldName()}" data-update-field="{$FIELD_MODEL->getFieldName()}" type="checkbox">&nbsp;
+										{/if}
 										{if $isReferenceField eq "reference"}
 											{if $refrenceListCount > 1}
 												{assign var="DISPLAYID" value=$FIELD_MODEL->get('fieldvalue')}
diff --git a/layouts/v7/modules/Vtiger/resources/List.js b/layouts/v7/modules/Vtiger/resources/List.js
index d6928a66c..a1ce13515 100644
--- a/layouts/v7/modules/Vtiger/resources/List.js
+++ b/layouts/v7/modules/Vtiger/resources/List.js
@@ -1204,9 +1204,15 @@ Vtiger.Class("Vtiger_List_Js", {
 			editInstance.registerBasicEvents(container);
 			var form_original_data = $("#massEdit").serialize();
 			$('#massEdit').on('submit', function (event) {
-				thisInstance.saveMassedit(event, form_original_data, isOwnerChanged);
+				thisInstance.saveMassEdit(event, form_original_data, isOwnerChanged);
 				isOwnerChanged = false;
 			});
+			
+			//automatically select fields for mass edit when updated
+			$('#massEdit :input').change(function() {
+				$(this).closest('tr').find("input[id^=include_in_mass_edit_" + $(this).attr('name') + "]").prop( "checked", true );
+			});
+			
 			app.helper.registerLeavePageWithoutSubmit($("#massEdit"));
 			app.helper.registerModalDismissWithoutSubmit($("#massEdit"));
 		});
@@ -1356,32 +1362,46 @@ Vtiger.Class("Vtiger_List_Js", {
         });
     },
     
-	saveMassedit: function (event, form_original_data, isOwnerChanged) {
+	saveMassEdit: function (event, form_original_data, isOwnerChanged) {
 		event.preventDefault();
 		var form = $('#massEdit');
 		var form_new_data = form.serialize();
+		var changedFields = form.find("input[id^=include_in_mass_edit_]:checked");
+		
 		app.helper.showProgress();
-		if (form_new_data !== form_original_data || isOwnerChanged) {
+		if (changedFields.length > 0 || isOwnerChanged) {
 			var originalData = app.convertUrlToDataParams(form_original_data);
 			var newData = app.convertUrlToDataParams(form_new_data);
 
-			for (var key in originalData) {
-				if ((form.find('[name="' + key + '"]').is("select")
-						|| form.find('[name="' + key + '"]').is("input[type='checkbox']"))
-						&& (originalData[key] == newData[key])) {
-					delete newData[key];
-				}
-			}
-
+			var form_update_data = '';
 			if (!newData['assigned_user_id'] && isOwnerChanged) {
-				newData['assigned_user_id'] = originalData['assigned_user_id'];
+				form_update_data += 'assigned_user_id=' + originalData['assigned_user_id'] + '&';
 			}
 
-			var form_update_data = '';
-			for (var key in newData) {
-				form_update_data += key + '=' + newData[key] + '&';
-			}
-			form_update_data = form_update_data.slice(0, -1);
+			//add url params for hidden fields needed for the save request
+			var hiddenFields = form.find("input[type=hidden]");
+			hiddenFields.each(function(i, obj){
+				key = $(this).attr("name");
+				
+				if (typeof newData[key] !== 'undefined') {
+					form_update_data += key + '=' + newData[key] + '&';
+				}
+			});
+			
+			//add url params for fields that will be updated
+			changedFields.each(function(i, obj){
+				var key = $(this).data("update-field");
+				var value = newData[key];
+				form_update_data += key + '=';
+				
+				if (typeof value !== 'undefined') {
+					form_update_data += newData[key];
+				}
+				form_update_data += '&';
+			});
+			
+			form_update_data = form_update_data.slice(0, -1);//remove last &
+			
 			app.request.post({data: form_update_data}).then(function (err, data) {
 				app.helper.hideProgress();
 				if (data) {
@@ -1398,6 +1418,7 @@ Vtiger.Class("Vtiger_List_Js", {
 			app.helper.showAlertBox({'message': app.vtranslate('NONE_OF_THE_FIELD_VALUES_ARE_CHANGED_IN_MASS_EDIT')});
 		}
 	},
+	
 	markSelectedIdsCheckboxes: function () {
 		var self = this;
 
@@ -2509,7 +2530,7 @@ Vtiger.Class("Vtiger_List_Js", {
 			self.registerFloatingThead();
 		});
 	},
-
+	
 	registerEvents: function () {
 		var thisInstance = this;
 		this._super();
diff --git a/modules/Vtiger/actions/MassSave.php b/modules/Vtiger/actions/MassSave.php
index c6ecc8dfe..8966268ab 100644
--- a/modules/Vtiger/actions/MassSave.php
+++ b/modules/Vtiger/actions/MassSave.php
@@ -21,7 +21,6 @@ class Vtiger_MassSave_Action extends Vtiger_Mass_Action {
 		try {
 			vglobal('VTIGER_TIMESTAMP_NO_CHANGE_MODE', $request->get('_timeStampNoChangeMode',false));
 			$moduleName = $request->getModule();
-			$moduleModel = Vtiger_Module_Model::getInstance($moduleName);
 			$recordModels = $this->getRecordModelsFromRequest($request);
 			$allRecordSave= true;
 			foreach($recordModels as $recordId => $recordModel) {
@@ -46,46 +45,40 @@ class Vtiger_MassSave_Action extends Vtiger_Mass_Action {
 	}
 
 	/**
-	 * Function to get the record model based on the request parameters
+	 * Function to get the updated record models
 	 * @param Vtiger_Request $request
-	 * @return Vtiger_Record_Model or Module specific Record Model instance
+	 * @return array of Vtiger_Record_Model
 	 */
-	function getRecordModelsFromRequest(Vtiger_Request $request) {
-
-		$moduleName = $request->getModule();
-		$moduleModel = Vtiger_Module_Model::getInstance($moduleName);
+	protected function getRecordModelsFromRequest(Vtiger_Request $request) {
 		$recordIds = $this->getRecordsListFromRequest($request);
 		$recordModels = array();
 
-		$fieldModelList = $moduleModel->getFields();
 		foreach($recordIds as $recordId) {
-			$recordModel = Vtiger_Record_Model::getInstanceById($recordId, $moduleModel);
-			$recordModel->set('id', $recordId);
-			$recordModel->set('mode', 'edit');
-
-			foreach ($fieldModelList as $fieldName => $fieldModel) {
+			$recordModels[$recordId] = $this->getUpdatedRecord($request, $recordId);
+		}
+		
+		return $recordModels;
+	}
+	
+	private function getUpdatedRecord(Vtiger_Request $request, $recordId) {
+		$recordModel = Vtiger_Record_Model::getInstanceById($recordId);
+		$recordModel->set('mode', 'edit');
+		$fieldModelList = $recordModel->getModule()->getFields();
+		
+		foreach ($fieldModelList as $fieldName => $fieldModel) {
+			if ($request->has($fieldName)) {
 				$fieldValue = $request->get($fieldName, null);
 				$fieldDataType = $fieldModel->getFieldDataType();
 				if($fieldDataType == 'time'){
 					$fieldValue = Vtiger_Time_UIType::getTimeValueWithSeconds($fieldValue);
 				}
-				if(isset($fieldValue) && $fieldValue != null) {
-					if(!is_array($fieldValue)) {
-						$fieldValue = trim($fieldValue);
-					}
-					$recordModel->set($fieldName, $fieldValue);
-				} else {
-					$uiType = $fieldModel->get('uitype');
-					if($uiType == 70) {
-						$recordModel->set($fieldName, $recordModel->get($fieldName));
-					}  else {
-						$uiTypeModel = $fieldModel->getUITypeModel();
-						$recordModel->set($fieldName, $uiTypeModel->getUserRequestValue($recordModel->get($fieldName)));
-					}
+				
+				if (!is_array($fieldValue)) {
+					$fieldValue = trim($fieldValue);
 				}
+				$recordModel->set($fieldName, $fieldValue);
 			}
-			$recordModels[$recordId] = $recordModel;
 		}
-		return $recordModels;
+		return $recordModel;
 	}
 }
-- 
GitLab