Merge pull request #13787 from eileenmcnaughton/label_button
[civicrm-core.git] / templates / CRM / Contact / Form / Merge.tpl
... / ...
CommitLineData
1{*
2 +--------------------------------------------------------------------+
3 | CiviCRM version 5 |
4 +--------------------------------------------------------------------+
5 | Copyright CiviCRM LLC (c) 2004-2019 |
6 +--------------------------------------------------------------------+
7 | This file is a part of CiviCRM. |
8 | |
9 | CiviCRM is free software; you can copy, modify, and distribute it |
10 | under the terms of the GNU Affero General Public License |
11 | Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
12 | |
13 | CiviCRM is distributed in the hope that it will be useful, but |
14 | WITHOUT ANY WARRANTY; without even the implied warranty of |
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
16 | See the GNU Affero General Public License for more details. |
17 | |
18 | You should have received a copy of the GNU Affero General Public |
19 | License and the CiviCRM Licensing Exception along |
20 | with this program; if not, contact CiviCRM LLC |
21 | at info[AT]civicrm[DOT]org. If you have questions about the |
22 | GNU Affero General Public License or the licensing of CiviCRM, |
23 | see the CiviCRM license FAQ at http://civicrm.org/licensing |
24 +--------------------------------------------------------------------+
25*}
26<div class="crm-block crm-form-block crm-contact-merge-form-block">
27 <div class="help">
28 {ts}Click <strong>Merge</strong> to move data from the Duplicate Contact on the left into the Main Contact. In addition to the contact data (address, phone, email...), you may choose to move all or some of the related activity records (groups, contributions, memberships, etc.).{/ts} {help id="intro"}
29 </div>
30
31 <div class="message status">
32 <div class="icon inform-icon"></div>
33 <strong>{ts}WARNING: The duplicate contact record WILL BE DELETED after the merge is complete.{/ts}</strong>
34 </div>
35
36 {if $user}
37 <div class="message status">
38 <div class="icon inform-icon"></div>
39 <strong>{ts 1=$config->userFramework}WARNING: There are %1 user accounts associated with both the original and duplicate contacts. Ensure that the %1 user you want to retain is on the right - if necessary use the 'Flip between original and duplicate contacts.' option at top to swap the positions of the two records before doing the merge.
40 The user record associated with the duplicate contact will not be deleted, but will be unlinked from the associated contact record (which will be deleted).
41 You will need to manually delete that user (click on the link to open the %1 user account in new screen). You may need to give thought to how you handle any content or contents associated with that user.{/ts}</strong>
42 </div>
43 {/if}
44
45 <div class="crm-submit-buttons">
46 {include file="CRM/common/formButtons.tpl" location="top"}
47 </div>
48
49 <div class="action-link">
50 {if $prev}<a href="{$prev}" class="crm-hover-button action-item"><i class="crm-i fa-chevron-left"></i> {ts}Previous{/ts}</a>{/if}
51 {if $next}<a href="{$next}" class="crm-hover-button action-item">{ts}Next{/ts} <i class="crm-i fa-chevron-right"></i></a>{/if}
52 <a href="{$flip}" class="action-item crm-hover-button">
53 <i class="crm-i fa-random"></i>
54 {ts}Flip between original and duplicate contacts.{/ts}
55 </a>
56 </div>
57
58 <div class="action-link">
59 <a href="#" class="action-item crm-hover-button crm-notDuplicate" title={ts}Mark this pair as not a duplicate.{/ts} onClick="processDupes( {$main_cid|escape}, {$other_cid|escape}, 'dupe-nondupe', 'merge-contact', '{$browseUrl}' );return false;">
60 <i class="crm-i fa-times-circle"></i>
61 {ts}Mark this pair as not a duplicate.{/ts}
62 </a>
63 </div>
64
65 <div class="action-link">
66 <a href="javascript:void(0);" class="action-item crm-hover-button toggle_equal_rows">
67 <i class="crm-i fa-eye-slash"></i>
68 {ts}Show/hide rows with the same data on each contact record.{/ts}
69 </a>
70 </div>
71
72 <table class="row-highlight">
73 <tr class="columnheader">
74 <th>&nbsp;</th>
75 <th><a href="{crmURL p='civicrm/contact/view' q="reset=1&cid=$other_cid"}">{$other_name|escape}</a> ({ts}duplicate{/ts})</th>
76 <th>{ts}Mark All{/ts}<br />=={$form.toggleSelect.html} ==&gt;</th>
77 <th><a href="{crmURL p='civicrm/contact/view' q="reset=1&cid=$main_cid"}">{$main_name|escape}</a></th>
78 <th width="300">Add/overwrite?</th>
79 </tr>
80
81 {crmAPI var='other_result' entity='Contact' action='get' return="modified_date" id=$other_cid}
82
83 {crmAPI var='main_result' entity='Contact' action='get' return="modified_date" id=$main_cid}
84
85 <tr>
86 <td>Last modified</td>
87 <td>{$other_result.values.0.modified_date|crmDate} {if $other_result.values.0.modified_date gt $main_result.values.0.modified_date} (Most recent) {/if}</td>
88 <td></td>
89 <td>{$main_result.values.0.modified_date|crmDate} {if $main_result.values.0.modified_date gt $other_result.values.0.modified_date} (Most recent) {/if}</td>
90 <td></td>
91 </tr>
92
93 {foreach from=$rows item=row key=field}
94
95 {if !isset($row.main) && !isset($row.other)}
96 <tr style="background-color: #fff !important; border-bottom:1px solid #ccc !important;" class="no-data">
97 <td>
98 <strong>{$row.title|escape}</strong>
99 </td>
100 {else}
101 {if $row.main eq $row.other}
102 <tr class="merge-row-equal crm-row-ok {cycle values="odd-row,even-row"}">
103 {else}
104 <tr class="crm-row-error {cycle values="odd-row,even-row"}">
105 {/if}
106 <td>
107 {$row.title|escape}
108 </td>
109 {/if}
110
111 {assign var=position value=$field|strrpos:'_'}
112 {assign var=blockId value=$field|substr:$position+1}
113 {assign var=blockName value=$field|substr:14:$position-14}
114
115 <td>
116 {* @TODO check if this is ever an array or a fileName? *}
117 {if $row.title|substr:0:5 == "Email" OR
118 $row.title|substr:0:7 == "Address"}
119 <span style="white-space: pre">
120 {else}
121 <span>
122 {/if}
123 {if !is_array($row.other)}
124 {$row.other|escape}
125 {elseif $row.other.fileName}
126 {$row.other.fileName|escape}
127 {else}
128 {', '|implode:$row.other}
129 {/if}
130 </span>
131 </td>
132
133 <td style='white-space: nowrap'>
134 {if $form.$field}=={$form.$field.html|crmAddClass:"select-row"}==&gt;{/if}
135 </td>
136
137 {* For location blocks *}
138 {if $row.title|substr:0:5 == "Email" OR
139 $row.title|substr:0:7 == "Address" OR
140 $row.title|substr:0:2 == "IM" OR
141 $row.title|substr:0:7 == "Website" OR
142 $row.title|substr:0:5 == "Phone"}
143
144 <td>
145 {strip}
146 {if $row.title|substr:0:5 == "Email" OR
147 $row.title|substr:0:7 == "Address"}
148 <span style="white-space: pre" id="main_{$blockName|escape}_{$blockId|escape}">
149 {else}
150 <span id="main_{$blockName|escape}_{$blockId|escape}">
151 {/if}
152 {* @TODO check if this is ever an array or a fileName? *}
153 {if !is_array($row.main)}
154 {$row.main|escape}
155 {elseif $row.main.fileName}
156 {$row.main.fileName|escape}
157 {else}
158 {', '|implode:$row.main}
159 {/if}
160 </span>
161 {/strip}
162 </td>
163
164 <td>
165 {* Display location for fields with locations *}
166 {if $blockName eq 'email' || $blockName eq 'phone' || $blockName eq 'address' || $blockName eq 'im' }
167 {$form.location_blocks.$blockName.$blockId.locTypeId.html}&nbsp;
168 {/if}
169
170 {* Display other_type_id for websites, ims and phones *}
171 {if $blockName eq 'website' || $blockName eq 'im' || $blockName eq 'phone' }
172 {$form.location_blocks.$blockName.$blockId.typeTypeId.html}&nbsp;
173 {/if}
174
175 {* Display the overwrite/add/add new label *}
176 <span id="main_{$blockName}_{$blockId}_overwrite" class="location_block_controls">
177
178 <span class="location_primary">
179 {if $row.main && $row.main_is_primary == "1"}Primary{/if}
180 </span>
181
182 <span class="location_block_controls_options">
183 <span class="location_operation_description">
184 {if $row.main}({ts}overwrite{/ts}){else}({ts}add{/ts}){/if}
185 </span>
186 <span style="display: block" class="location_operation_checkbox">
187 {if $row.main && ($blockName eq 'email' || $blockName eq 'phone')}
188 {$form.location_blocks.$blockName.$blockId.operation.html}
189 {/if}
190 </span>
191 <span style="display: block" class="location_set_other_primary">
192 {if $blockName neq 'website' && (($row.main && $row.main_is_primary != "1") || !$row.main)}
193 {$form.location_blocks.$blockName.$blockId.set_other_primary.html}
194 {/if}
195 </span>
196 </span>
197 </span>
198
199 </td>
200
201 {* For non-location blocks *}
202 {else}
203
204 <td>
205 <span>
206 {if !is_array($row.main)}
207 {$row.main|escape}
208 {elseif $row.main.fileName}
209 {$row.main.fileName|escape}
210 {else}
211 {', '|implode:$row.main}
212 {/if}
213 </span>
214 </td>
215
216 <td>
217 {if isset($row.main) || isset($row.other)}
218 <span>
219 {if $row.main == $row.other}
220 <span class="action_label">({ts}match{/ts})</span><br />
221 {elseif $row.main}
222 <span class="action_label">({ts}overwrite{/ts})</span><br />
223 {else}
224 <span class="action_label">({ts}add{/ts})</span>
225 {/if}
226 </span>
227 {/if}
228 </td>
229
230 {/if}
231
232 </tr>
233 {/foreach}
234
235 {foreach from=$rel_tables item=params key=paramName}
236 {if $paramName eq 'move_rel_table_users'}
237 <tr class="{cycle values="even-row,odd-row"}">
238 <td><strong>{ts}Move related...{/ts}</strong></td><td>{if $otherUfId}<a target="_blank" href="{$params.other_url}">{$otherUfName}</a></td><td style='white-space: nowrap'>=={$form.$paramName.html|crmAddClass:"select-row"}==&gt;{else}<td style='white-space: nowrap'></td>{/if}</td><td>{if $mainUfId}<a target="_blank" href="{$params.main_url}">{$mainUfName}</a>{/if}</td>
239 <td>({ts}migrate{/ts})</td>
240 </tr>
241 {else}
242 <tr class="{cycle values="even-row,odd-row"}">
243 <td><strong>{ts}Move related...{/ts}</strong></td><td><a href="{$params.other_url}">{$params.title}</a></td><td style='white-space: nowrap'>=={$form.$paramName.html|crmAddClass:"select-row"}==&gt;</td><td><a href="{$params.main_url}">{$params.title}</a>{if $form.operation.$paramName.add.html}&nbsp;{$form.operation.$paramName.add.html}{/if}</td>
244 <td>({ts}migrate{/ts})</td>
245 </tr>
246 {/if}
247 {/foreach}
248 </table>
249
250 <div class="crm-submit-buttons">
251 {include file="CRM/common/formButtons.tpl" location="bottom"}
252 </div>
253</div>
254
255{literal}
256<script type="text/javascript">
257
258 var locationBlockInfo = {/literal}{$locationBlockInfo}{literal};
259 var allBlock = {/literal}{$mainLocBlock}{literal};
260
261 /**
262 * Triggered when a 'location' or 'type' destination is changed, and when
263 * the operation or 'set primary' checkboxes are changed.
264 *
265 * Check to see if the 'main' contact record has a corresponding location
266 * block when the destination of a field is changed. Allow existing location
267 * fields to be overwritten with data from the 'other' contact.
268 *
269 * @param blockName string
270 * The name of the entity.
271 * @param blockId int
272 * The block ID being affected.
273 * @param event object
274 * The event that triggered the update.
275 */
276 function updateMainLocationBlock(blockName, blockId, event) {
277
278 // Get type of select list that's been changed (location or type)
279 var locTypeId = CRM.$('select#location_blocks_' + blockName + '_' + blockId + '_locTypeId').val();
280 var typeTypeId = CRM.$('select#location_blocks_' + blockName + '_' + blockId + '_typeTypeId').val();
281
282 // @todo Fix this 'special handling' for websites (no location id)
283 if (!locTypeId) {
284 locTypeId = 0;
285 }
286
287 // Look for a matching block on the main contact
288 var mainBlockId = 0;
289 var mainBlockDisplay = '';
290 var mainBlock = findBlock(blockName, locTypeId, typeTypeId);
291 if (mainBlock != false) {
292 mainBlockDisplay = mainBlock['display'];
293 mainBlockId = mainBlock['id'];
294 }
295
296 // Update main location display and id
297 CRM.$("input[name='location_blocks[" + blockName + "][" + blockId + "][mainContactBlockId]']").val(mainBlockId);
298 CRM.$("#main_" + blockName + "_" + blockId).html(mainBlockDisplay);
299
300 // Update controls area
301
302 // Get the parent block once for speed
303 var this_controls = CRM.$("#main_" + blockName + "_" + blockId + "_overwrite");
304
305 // Update primary label
306 if (mainBlock != false && mainBlock['is_primary'] == '1') {
307 this_controls.find(".location_primary").text('Primary');
308 }
309 else {
310 this_controls.find(".location_primary").text('');
311 }
312
313 // Update operation description
314 var operation_description = "{/literal}{ts escape='js'}add{/ts}{literal}";
315 var add_new_check_length = this_controls.find(".location_operation_checkbox input:checked").length;
316 if (mainBlock != false) {
317 if (add_new_check_length > 0) {
318 operation_description = "{/literal}{ts}add new{/ts}{literal}";
319 }
320 else {
321 operation_description = "{/literal}{ts}overwrite{/ts}{literal}";
322 }
323 }
324 this_controls.find(".location_operation_description").text("(" + operation_description + ")");
325
326 // Skip if the 'add new' or 'set primary' checkboxes were clicked
327 if (event.target.id.match(/(operation|set_other_primary)/) === null) {
328 // Display 'Add new' checkbox if there is a main block, and this is an
329 // email or phone type.
330 if (mainBlock != false && (blockName == 'email' || blockName == 'phone')) {
331 var op_id = 'location_blocks[' + blockName + '][' + blockId + '][operation]';
332 this_controls.find(".location_operation_checkbox").html(
333 '<input id="' + op_id + '" name="' + op_id + '" type="checkbox" value="1" class="crm-form-checkbox"><label for="' + op_id + '">{/literal}{ts}Add new{/ts}{literal}</label>'
334 );
335 }
336 else {
337 this_controls.find(".location_operation_checkbox").html('');
338 }
339 }
340
341 // Skip if 'set primary' was clicked
342 if (event.target.id.match(/(set_other_primary)/) === null) {
343 // Display 'Set primary' checkbox if applicable
344 if (blockName != 'website' && (mainBlock == false || mainBlock['is_primary'] != "1" || add_new_check_length > 0)) {
345 var prim_id = 'location_blocks[' + blockName + '][' + blockId + '][set_other_primary]';
346 this_controls.find(".location_set_other_primary").html(
347 '<input id="' + prim_id + '" name="' + prim_id + '" type="checkbox" value="1" class="crm-form-checkbox"><label for="' + prim_id + '">{/literal}{ts}Set as primary{/ts}{literal}</label>'
348 );
349 }
350 else {
351 this_controls.find(".location_set_other_primary").html('');
352 }
353 }
354
355 }
356
357 /**
358 * Look for a matching 'main' contact location block by entity, location and
359 * type
360 *
361 * @param entName string
362 * The entity name to lookup.
363 * @param locationID int
364 * The location ID to lookup.
365 * @param typeID int
366 * The type ID to lookup.
367 *
368 * @returns boolean|object
369 * Returns false if no match, otherwise an object with the location ID and
370 * display value.
371 */
372 function findBlock(entName, locationID, typeID) {
373 var entityArray = allBlock[entName];
374 var result = false;
375 for (var i = 0; i < entityArray.length; i++) {
376 // Match based on location and type ID, depending on the entity info
377 if (locationBlockInfo[entName]['hasLocation'] == false || locationID == entityArray[i]['location_type_id']) {
378 if (locationBlockInfo[entName]['hasType'] == false || typeID == entityArray[i][locationBlockInfo[entName]['hasType']]) {
379 result = {
380 display: entityArray[i][locationBlockInfo[entName]['displayField']],
381 id: entityArray[i]['id'],
382 is_primary: entityArray[i]['is_primary']
383 };
384 break;
385 }
386 }
387 }
388 return result;
389 }
390
391 /**
392 * Called when a 'set primary' checkbox is clicked in order to disable any
393 * other 'set primary' checkboxes for blocks of the same entity. So don't let
394 * users try to set two different phone numbers as primary on the form.
395 *
396 * @param event object
397 * The event that triggered the update
398 */
399 function updateSetPrimaries(event) {
400 var nameSplit = event.target.name.split('[');
401 var blockName = nameSplit[1].slice(0, -1);
402 var controls = CRM.$('span.location_block_controls[id^="main_' + blockName + '"]');
403
404 // Enable everything
405 controls.find('input[id$="[set_other_primary]"]:not(:checked)').removeAttr("disabled");
406
407 // If one is checked, disable the others
408 if (controls.find('input[id$="[set_other_primary]"]:checked').length > 0) {
409 controls.find('input[id$="[set_other_primary]"]:not(:checked)').attr("disabled", "disabled");
410 }
411 }
412
413 /**
414 * Toggle the location type and the is_primary on & off depending on whether the merge box is ticked.
415 *
416 * @param element
417 */
418 function toggleRelatedLocationFields(element) {
419 relatedElements = CRM.$(element).parent().siblings('td').find('input,select,label,hidden');
420 if (CRM.$(element).is(':checked')) {
421 relatedElements.removeClass('disabled').attr('disabled', false);
422
423 }
424 else {
425 relatedElements.addClass('disabled').attr('disabled', true);
426 }
427
428 }
429
430 CRM.$(function($) {
431 $('input.crm-form-checkbox[data-is_location]').on('click', function(){
432 toggleRelatedLocationFields(this)
433 });
434
435 // Show/hide matching data rows
436 $('.toggle_equal_rows').click(function() {
437 $('tr.merge-row-equal').toggle();
438 });
439
440 // Call mergeBlock whenever a location type is changed
441 // (This is applied to the body because the inputs can be added dynamically
442 // to the form, and we need to catch when they change.)
443 $('body').on('change', 'select[id$="locTypeId"],select[id$="typeTypeId"],input[id$="[operation]"],input[id$="[set_other_primary]"]', function(event){
444
445 // All the information we need is held in the id, separated by underscores
446 var nameSplit = this.name.split('[');
447
448 // Lookup the main value, if any are available
449 if (allBlock[nameSplit[1].slice(0, -1)] != undefined) {
450 updateMainLocationBlock(nameSplit[1].slice(0, -1), nameSplit[2].slice(0, -1), event);
451 }
452
453 // Update all 'set primary' checkboxes
454 updateSetPrimaries(event);
455
456 });
457
458 });
459
460</script>
461{/literal}
462
463{* process the dupe contacts *}
464{include file="CRM/common/dedupe.tpl"}