Merge pull request #15933 from civicrm/5.20
[civicrm-core.git] / templates / CRM / Contact / Page / DedupeFind.tpl
1 {*
2 +--------------------------------------------------------------------+
3 | Copyright CiviCRM LLC. All rights reserved. |
4 | |
5 | This work is published under the GNU AGPLv3 license with some |
6 | permitted exceptions and without any warranty. For full license |
7 | and copyright information, see https://civicrm.org/licensing |
8 +--------------------------------------------------------------------+
9 *}
10 {if $action eq 2 || $action eq 16}
11 <div class="form-item">
12 <div class="crm-accordion-wrapper crm-search_filters-accordion">
13 <div class="crm-accordion-header">
14 {ts}Filter Contacts{/ts}</a>
15 </div><!-- /.crm-accordion-header -->
16 <div class="crm-accordion-body">
17 <table class="no-border form-layout-compressed" id="searchOptions" style="width:100%;">
18 <tr>
19 <td class="crm-contact-form-block-contact1">
20 <label for="contact1">{ts}Contact 1{/ts}</label><br />
21 <input type="text" placeholder="Search Contact1" search-column="2" />
22 </td>
23 <td class="crm-contact-form-block-contact2">
24 <label for="contact2">{ts}Contact 2{/ts}</label><br />
25 <input type="text" placeholder="Search Contact2" search-column="4" />
26 </td>
27 <td class="crm-contact-form-block-email1">
28 <label for="email1">{ts}Email 1{/ts}</label><br />
29 <input type="text" placeholder="Search Email1" search-column="5" />
30 </td>
31 <td class="crm-contact-form-block-email2">
32 <label for="email2">{ts}Email 2{/ts}</label><br />
33 <input type="text" placeholder="Search Email2" search-column="6" />
34 </td>
35 </tr>
36 <tr>
37 <td class="crm-contact-form-block-street-address1">
38 <label for="street-adddress1">{ts}Street Address 1{/ts}</label><br />
39 <input type="text" placeholder="Search Street Address1" search-column="7" />
40 </td>
41 <td class="crm-contact-form-block-street-address2">
42 <label for="street-adddress2">{ts}Street Address 2{/ts}</label><br />
43 <input type="text" placeholder="Search Street Address2" search-column="8" />
44 </td>
45 <td class="crm-contact-form-block-postcode1">
46 <label for="postcode1">{ts}Postcode 1{/ts}</label><br />
47 <input type="text" placeholder="Search Postcode1" search-column="9" />
48 </td>
49 <td class="crm-contact-form-block-postcode2">
50 <label for="postcode2">{ts}Postcode 2{/ts}</label><br />
51 <input type="text" placeholder="Search Postcode2" search-column="10" />
52 </td>
53 </tr>
54 </table>
55 </div><!-- /.crm-accordion-body -->
56 </div><!-- /.crm-accordion-wrapper -->
57 <div>
58 Show / Hide columns:
59 <input type='checkbox' id ='steet-address' class='toggle-vis' data-column-main="7" data-column-dupe="8" >
60 <label for="steet-address">{ts}Street Address{/ts}&nbsp;</label>
61 <input type='checkbox' id ='post-code' class='toggle-vis' data-column-main="9" data-column-dupe="10" >
62 <label for="post-code">{ts}Post Code{/ts}&nbsp;</label>
63 <input type='checkbox' id ='conflicts' class='toggle-vis' data-column-main="11" >
64 <label for="conflicts">{ts}Conflicts{/ts}&nbsp; </label>
65 <input type='checkbox' id ='threshold' class='toggle-vis' data-column-main="12" >
66 <label for="threshold">{ts}Threshold{/ts}&nbsp;</label>
67 </div><br/>
68 <span id="dupePairs_length_selection">
69 <input type='checkbox' id ='crm-dedupe-display-selection' name="display-selection">
70 <label for="display-selection">{ts}Within Selections{/ts}&nbsp;</label>
71 </span>
72
73 <table id="dupePairs"
74 class="nestedActivitySelector crm-ajax-table"
75 cellspacing="0"
76 width="100%"
77 data-page-length="10",
78 data-searching='true',
79 data-dom='flrtip',
80 data-order='[]',
81 data-column-defs='{literal}[{"targets": [0,1,3,13], "orderable":false}, {"targets": [7,8,9,10,11,12], "visible":false}]{/literal}'>
82 <thead>
83 <tr class="columnheader">
84 <th data-data="is_selected_input" class="crm-dedupe-selection"><input type="checkbox" value="0" name="pnid_all" class="crm-dedupe-select-all"></th>
85 <th data-data="dst_image" class="crm-empty">&nbsp;</th>
86 <th data-data="dst" class="crm-contact">{ts}Contact{/ts} 1</th>
87 <th data-data="src_image" class="crm-empty">&nbsp;</th>
88 <th data-data="src" class="crm-contact-duplicate">{ts}Contact{/ts} 2 ({ts}Duplicate{/ts})</th>
89 <th data-data="dst_email" class="crm-contact">{ts}Email{/ts} 1</th>
90 <th data-data="src_email" class="crm-contact-duplicate">{ts}Email{/ts} 2 ({ts}Duplicate{/ts})</th>
91 <th data-data="dst_street" class="crm-contact">{ts}Street Address{/ts} 1</th>
92 <th data-data="src_street" class="crm-contact-duplicate">{ts}Street Address{/ts} 2 ({ts}Duplicate{/ts})</th>
93 <th data-data="dst_postcode" class="crm-contact">{ts}Postcode{/ts} 1</th>
94 <th data-data="src_postcode" class="crm-contact-duplicate">{ts}Postcode{/ts} 2 ({ts}Duplicate{/ts})</th>
95 <th data-data="conflicts" class="crm-contact-conflicts">{ts}Conflicts{/ts}</th>
96 <th data-data="weight" class="crm-threshold">{ts}Threshold{/ts}</th>
97 <th data-data="actions" class="crm-empty">&nbsp;</th>
98 </tr>
99 </thead>
100 <tbody>
101 </tbody>
102 </table>
103 </div>
104
105 {if $context eq 'search'}
106 {crmButton href=$backURL icon="times"}{ts}Done{/ts}{/crmButton}
107 {elseif $context eq 'conflicts'}
108 {if call_user_func(array('CRM_Core_Permission','check'), 'force merge duplicate contacts')}
109 {capture assign=backURL}{crmURL p="civicrm/contact/dedupemerge" q="`$urlQuery`&action=map&mode=aggressive" a=1}{/capture}
110 <a href="{$backURL}" title="{ts}Force Merge Selected Duplicates{/ts}" onclick="return confirm('{ts escape="js"}This will run the batch merge process on the selected duplicates. The operation will run in force merge mode - all selected duplicates will be merged into main contacts even in case of any conflicts. Click OK to proceed if you are sure you wish to run this operation.{/ts}');" class="button"><span><i class="crm-i fa-bolt"></i> {ts}Force Merge Selected Duplicates{/ts}</span></a>
111
112 {capture assign=backURL}{crmURL p="civicrm/contact/dedupemerge" q="`$urlQuery`&action=map" a=1}{/capture}
113 <a href="{$backURL}" title="{ts}Safe Merge Selected Duplicates{/ts}" onclick="return confirm('{ts escape="js"}This will run the batch merge process on the selected duplicates. The operation will run in safe mode - only records with no direct data conflicts will be merged. Click OK to proceed if you are sure you wish to run this operation.{/ts}');" class="button"><span><i class="crm-i fa-compress"></i> {ts}Safe Merge Selected Duplicates{/ts}</span></a>
114 {/if}
115
116 {capture assign=backURL}{crmURL p="civicrm/contact/dedupefind" q="`$urlQuery`&action=update&selected=0" a=1}{/capture}
117 <a href="{$backURL}" title="{ts}List All Duplicates{/ts}" class="button"><span><i class="crm-i fa-refresh"></i> {ts}List All Duplicates{/ts}</span></a>
118 {else}
119 {capture assign=backURL}{crmURL p="civicrm/contact/dedupefind" q="`$urlQuery`&action=renew" a=1}{/capture}
120 <a href="{$backURL}" title="{ts}Refresh List of Duplicates{/ts}" onclick="return confirm('{ts escape="js"}This will refresh the duplicates list. Click OK to proceed.{/ts}');" class="button">
121 <span><i class="crm-i fa-refresh"></i> {ts}Refresh Duplicates{/ts}</span>
122 </a>
123
124 {capture assign=backURL}{crmURL p="civicrm/contact/dedupemerge" q="`$urlQuery`&action=map" a=1}{/capture}
125 <a href="{$backURL}" title="{ts}Batch Merge Duplicate Contacts{/ts}" onclick="return confirm('{ts escape="js"}This will run the batch merge process on the selected duplicates. The operation will run in safe mode - only records with no direct data conflicts will be merged. Click OK to proceed if you are sure you wish to run this operation.{/ts}');" class="button"><span><i class="crm-i fa-compress"></i> {ts}Batch Merge Selected Duplicates{/ts}</span></a>
126
127 {capture assign=backURL}{crmURL p="civicrm/contact/dedupemerge" q=$urlQuery a=1}{/capture}
128 <a href="{$backURL}" title="{ts}Batch Merge Duplicate Contacts{/ts}" onclick="return confirm('{ts escape="js"}This will run the batch merge process on the listed duplicates. The operation will run in safe mode - only records with no direct data conflicts will be merged. Click OK to proceed if you are sure you wish to run this operation.{/ts}');" class="button"><span><i class="crm-i fa-compress"></i> {ts}Batch Merge All Duplicates{/ts}</span></a>
129
130 <a href='#' title="{ts}Flip Selected Duplicates{/ts}" class="crm-dedupe-flip-selections button"><span><i class="crm-i fa-exchange"></i> {ts}Flip Selected Duplicates{/ts}</span></a>
131
132 {capture assign=backURL}{crmURL p="civicrm/contact/deduperules" q="reset=1" a=1}{/capture}
133 <a href="{$backURL}" class="button crm-button-type-cancel">
134 <span><i class="crm-i fa-times"></i> {ts}Done{/ts}</span>
135 </a>
136 {/if}
137 <div style="clear: both;"></div>
138 {else}
139 {include file="CRM/Contact/Form/DedupeFind.tpl"}
140 {/if}
141
142 {* process the dupe contacts *}
143 {include file='CRM/common/dedupe.tpl'}
144 {literal}
145 <script type="text/javascript">
146 (function($) {
147 CRM.$('table#dupePairs').data({
148 "ajax": {
149 "url": {/literal}'{$sourceUrl}{if $isSelected}&selected=1{/if}'{literal}
150 },
151 "retrieve": true,
152 "processing": true,
153 "serverSide": true,
154 rowCallback: function (row, data) {
155 // Set the checked state of the checkbox in the table
156 $('input.crm-dedupe-select', row).prop('checked', data.is_selected == 1);
157 if (data.is_selected == 1) {
158 $(row).toggleClass('crm-row-selected');
159 }
160 // for action column at the last, set nowrap
161 $('td:last', row).attr('nowrap','nowrap');
162 // for conflicts column
163 var col = CRM.$('table#dupePairs thead th.crm-contact-conflicts').index();
164 $('td:eq(' + col + ')', row).attr('nowrap','nowrap');
165 }
166 });
167 $(function($) {
168
169 var sourceUrl = {/literal}'{$sourceUrl}'{literal};
170 var context = {/literal}'{$context}'{literal};
171
172 // redraw datatable if searching within selected records
173 $('#crm-dedupe-display-selection').on('click', function(){
174 reloadUrl = sourceUrl;
175 if($(this).prop('checked')){
176 reloadUrl = sourceUrl+'&selected=1';
177 }
178 CRM.$('table#dupePairs').DataTable().ajax.url(reloadUrl).draw();
179 });
180
181 $('#dupePairs_length_selection').appendTo('#dupePairs_length');
182
183 // apply selected class on click of a row
184 $('#dupePairs tbody').on('click', 'tr', function(e) {
185 $(this).toggleClass('crm-row-selected');
186 $('input.crm-dedupe-select', this).prop('checked', $(this).hasClass('crm-row-selected'));
187 var ele = $('input.crm-dedupe-select', this);
188 toggleDedupeSelect(ele, 0);
189 });
190
191 // when select-all checkbox is checked
192 $('#dupePairs thead tr .crm-dedupe-selection').on('click', function() {
193 var checked = $('.crm-dedupe-select-all').prop('checked');
194 if (checked) {
195 $("#dupePairs tbody tr input[type='checkbox']").prop('checked', true);
196 $("#dupePairs tbody tr").addClass('crm-row-selected');
197 }
198 else{
199 $("#dupePairs tbody tr input[type='checkbox']").prop('checked', false);
200 $("#dupePairs tbody tr").removeClass('crm-row-selected');
201 }
202 var ele = $('#dupePairs tbody tr');
203 toggleDedupeSelect(ele, 1);
204 });
205
206 // inline search boxes placed in tfoot
207 $('#dupePairsColFilters thead th').each( function () {
208 var title = $('#dupePairs thead th').eq($(this).index()).text();
209 if (title.length > 1) {
210 $(this).html( '<input type="text" placeholder="Search '+title+'" />' );
211 }
212 });
213
214 // apply the search
215 $('#searchOptions input').on( 'keyup change', function () {
216 $('table#dupePairs').DataTable()
217 .column($(this).attr('search-column'))
218 .search(this.value)
219 .draw();
220 });
221
222 // show / hide columns
223 $('input.toggle-vis').on('click', function (e) {
224 var column = $('table#dupePairs').DataTable().column( $(this).attr('data-column-main') );
225 column.visible( ! column.visible() );
226
227 // nowrap to conflicts column is applied only during initial rendering
228 // for show / hide clicks we need to set it explicitly
229 var col = CRM.$('table#dupePairs thead th.crm-contact-conflicts').index() + 1;
230 if (col > 0) {
231 CRM.$('table#dupePairs tbody tr td:nth-child(' + col + ')').attr('nowrap','nowrap');
232 }
233
234 if ($(this).attr('data-column-dupe')) {
235 column = $('table#dupePairs').DataTable().column( $(this).attr('data-column-dupe') );
236 column.visible( ! column.visible() );
237 }
238 });
239
240 // keep the conflicts checkbox checked when context is "conflicts"
241 if(context == 'conflicts') {
242 $('#conflicts').attr('checked', true);
243 var column = $('table#dupePairs').DataTable().column( $('#conflicts').attr('data-column-main') );
244 column.visible( ! column.visible() );
245 }
246
247 // on click of flip link of a row
248 $('#dupePairs tbody').on('click', 'tr .crm-dedupe-flip', function(e) {
249 e.stopPropagation();
250 var $el = $(this);
251 var $elTr = $(this).closest('tr');
252 var postUrl = {/literal}"{crmURL p='civicrm/ajax/flipDupePairs' h=0 q='snippet=4'}"{literal};
253 var request = $.post(postUrl, {pnid : $el.data('pnid')});
254 request.done(function(dt) {
255 var mapper = {1:3, 2:4, 5:6, 7:8, 9:10}
256 var idx = $('table#dupePairs').DataTable().row($elTr).index();
257 $.each(mapper, function(key, val) {
258 var v1 = $('table#dupePairs').DataTable().cell(idx, key).data();
259 var v2 = $('table#dupePairs').DataTable().cell(idx, val).data();
260 $('table#dupePairs').DataTable().cell(idx, key).data(v2);
261 $('table#dupePairs').DataTable().cell(idx, val).data(v1);
262 });
263 // keep the checkbox checked if needed
264 $('input.crm-dedupe-select', $elTr).prop('checked', $elTr.hasClass('crm-row-selected'));
265 });
266 });
267
268 $(".crm-dedupe-flip-selections").on('click', function(e) {
269 e.preventDefault();
270 var ids = [];
271 $('.crm-row-selected').each(function() {
272 var ele = CRM.$('input.crm-dedupe-select', this);
273 ids.push(CRM.$(ele).attr('name').substr(5));
274 });
275 if (ids.length > 0) {
276 var dataUrl = {/literal}"{crmURL p='civicrm/ajax/flipDupePairs' h=0 q='snippet=4'}"{literal};
277 var request = $.post(dataUrl, {pnid: ids});
278 request.done(function(dt) {
279 var mapper = {1:3, 2:4, 5:6, 7:8, 9:10}
280 $('.crm-row-selected').each(function() {
281 var idx = $('table#dupePairs').DataTable().row(this).index();
282 $.each(mapper, function(key, val) {
283 var v1 = $('table#dupePairs').DataTable().cell(idx, key).data();
284 var v2 = $('table#dupePairs').DataTable().cell(idx, val).data();
285 $('table#dupePairs').DataTable().cell(idx, key).data(v2);
286 $('table#dupePairs').DataTable().cell(idx, val).data(v1);
287 });
288 // keep the checkbox checked if needed
289 $('input.crm-dedupe-select', this).prop('checked', $(this).hasClass('crm-row-selected'));
290 });
291 });
292 }
293 });
294 });
295 })(CRM.$);
296
297 function toggleDedupeSelect(element, isMultiple) {
298 if (!isMultiple) {
299 var is_selected = CRM.$(element).prop('checked') ? 1: 0;
300 var id = CRM.$(element).prop('name').substr(5);
301 }
302 else {
303 var id = [];
304 CRM.$(element).each(function() {
305 var pnName = CRM.$('input.crm-dedupe-select', this).prop('name');
306 if (pnName !== undefined) {
307 id.push(pnName.substr(5));
308 }
309 });
310 var is_selected = CRM.$('.crm-dedupe-select-all').prop('checked') ? 1 : 0;
311 }
312
313 var cacheKey = {/literal}'{$cacheKey|escape}'{literal};
314
315 var dataUrl = {/literal}"{crmURL p='civicrm/ajax/toggleDedupeSelect' h=0 q='snippet=4'}"{literal};
316 var rgid = {/literal}"{$rgid}"{literal};
317 var gid = {/literal}"{$gid}"{literal};
318
319 rgid = rgid.length > 0 ? rgid : 0;
320 gid = gid.length > 0 ? gid : 0;
321
322 CRM.$.post(dataUrl, {pnid: id, rgid: rgid, gid: gid, is_selected: is_selected, cacheKey : cacheKey}, function (data) {
323 // nothing to do for now
324 }, 'json');
325 }
326 </script>
327 {/literal}