main.js 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729
  1. //CHARGEMENT DE LA PAGE
  2. function init_plugin_client(){
  3. switch($.urlParam('page')){
  4. case 'sheet.client':
  5. //Convertit les téléphones en lien appellable si on est sur mobile
  6. if(is_phone()) $('[data-type="phone-text"]').replaceWith(function(i,text){
  7. return '<a href="tel:'+text+'">'+text+'</a>';
  8. });
  9. client_contact_search();
  10. client_address_search(client_tab_refresh);
  11. client_relation_search();
  12. window.onhashchange = function(event){
  13. client_tab_refresh();
  14. };
  15. client_image_edit('.client-summary-panel .client-thumbnail','cover-thumbnail');
  16. break;
  17. default:
  18. break;
  19. }
  20. $(document).click(function(){
  21. $('#client-api .dropdown-menu').hide();
  22. });
  23. }
  24. function client_import(){
  25. var data = $('.client-setting-form').toJson();
  26. data.action = 'client_import';
  27. $.action(data,function(){
  28. $.message('success','Importé');
  29. });
  30. }
  31. function client_switch_pseudonym(value){
  32. if(value){
  33. $('.block-label').addClass('hidden');
  34. $('.block-pseudonym').removeClass('hidden');
  35. }else{
  36. $('.block-pseudonym').addClass('hidden');
  37. $('.block-label').removeClass('hidden');
  38. }
  39. }
  40. function client_tab_refresh(){
  41. var tab = $.hashData('tab');
  42. tab = tab == '' ? 'home': tab;
  43. $('.client-menu-bar ul li').removeClass('active');
  44. $('.client-menu-bar ul li[data-slug="'+tab+'"]').addClass('active');
  45. $('.client-content-page').load('action.php?action=client_tab_load&tab='+tab+'&id='+$('.client-container').attr('data-id'),function(){
  46. init_components('.client-content-page');
  47. var init = 'client_tab_init_'+tab;
  48. init = init.replace(/[^a-z_0-9]/g,'_');
  49. if(window[init]!=null) window[init]($.urlParam());
  50. });
  51. }
  52. function client_tab_init_home(){
  53. client_type_change();
  54. client_live_update();
  55. client_image_edit('.client-form .client-thumbnail','logo-thumbnail');
  56. client_address_change();
  57. }
  58. function client_image_edit(element,fileId){
  59. var element = $(element);
  60. element.addClass('client-image-edit');
  61. var input = $('<input type="file" id="'+fileId+'" class="hidden">');
  62. var button = $('<div class="client-image-edit-button editable-only"><i class="fas fa-pencil-alt"></i></div>');
  63. element.append(button);
  64. element.after(input);
  65. if( $('.client-container').attr('data-editable') =='0' ) return;
  66. element.click(function(){
  67. input.change(function(){
  68. var reader = new FileReader();
  69. reader.onload = function (e) {
  70. element.attr('style','background-image: url('+e.target.result+');background-color:#efefef;');
  71. }
  72. reader.readAsDataURL(input.get(0).files[0]);
  73. });
  74. input.click();
  75. });
  76. }
  77. function client_name_change(){
  78. var label = $('#label');
  79. var fullName = $('#firstname').val()+' '+$('#name').val().toUpperCase();
  80. label.val(fullName).keyup();
  81. }
  82. function client_type_change(){
  83. var value = $('.type-choice input:checked').val();
  84. $('.client-container').attr('data-client-type',value);
  85. client_address_change();
  86. }
  87. function client_address_change(element){
  88. client_update_map_size();
  89. if(!$('.client-form').hasClass('client-form-map') || !$('#addresses li:not(.hidden)').length) return;
  90. var element = element!=null ? $(element) : $('#addresses li[data-type="global"]');
  91. element = element.length ? element : $('#addresses li:not(.hidden)').first();
  92. var address = element.data();
  93. var addressLabel = address.street+' '+address.city+', '+address.zip;
  94. var url = "https://maps.google.com/maps?q="+encodeURI(addressLabel) +"&t=&z=13&ie=UTF8&iwloc=&output=embed";
  95. $('#gmap_canvas').attr('src', url);
  96. if(address && !is_empty_obj(address))
  97. $('.client-city span').text(address.city+' ('+address.zip+')')
  98. }
  99. function client_toggle_more_fields(element){
  100. $('#more-fields-container').toggleClass('hidden');
  101. if(element!=null) $(element).find('i').toggleClass('fa-chevron-down').toggleClass('fa-chevron-up');
  102. client_update_map_size();
  103. }
  104. function client_live_update(){
  105. $('[data-live-update]').each(function(){
  106. var tag = $(this);
  107. var selector = tag.attr('data-live-update');
  108. $(selector).on('keyup',function(){
  109. tag.text($(selector).val());
  110. }).keyup();
  111. });
  112. }
  113. function client_internet_modal(){
  114. $('#client-internet-modal').modal('show');
  115. client_api_search();
  116. }
  117. function client_api_search(){
  118. var label = $('#label').val();
  119. if(!label) return $.message('warning','Vous devez remplir le libellé pour lancer une recherche');
  120. var choices = $('#client-internet-modal .choices');
  121. var city = $('.client-city').attr('data-city');
  122. var zip = $('.client-city').attr('data-zip');
  123. $('#client-internet-modal .modal-preloader').addClass('btn-preloader');
  124. $('#client-internet-modal .choices').fill({
  125. action: 'client_api_search',
  126. label: label
  127. },function(r){
  128. for(var k in r.rows){
  129. var row = r.rows[k];
  130. var li = $('#client-internet-modal .choices li:eq('+(parseInt(k) + 1)+')');
  131. if( (city && row.city.indexOf(city) !== -1) || (zip && row.zip == zip) ) li.find('h5').addClass('text-warning');
  132. li.data('infos',row);
  133. }
  134. $('#client-internet-modal .modal-preloader').removeClass('btn-preloader');
  135. });
  136. }
  137. function client_api_load(li){
  138. var li = $(li);
  139. var infos = li.data('infos');
  140. $('#label').val(infos.label);
  141. $('#job').val(infos.job);
  142. $('#siret').val(infos.siret);
  143. var comment = $('#comment').val();
  144. if(comment) comment+'\n';
  145. $('#comment').val(comment+"Taille : "+infos.size+' - (environ '+infos.employees+' employés'+"\n"+infos.status+" - SIREN : "+infos.siren+"\n"+" Société fondée le : "+infos.created);
  146. $('#client-internet-modal').modal('hide');
  147. client_client_save(function(client){
  148. client_address_save({
  149. "type": "global",
  150. "street": infos.street,
  151. "complement": "",
  152. "city": infos.city,
  153. "zip": infos.zip,
  154. "country": "France"
  155. },function(){
  156. $.message('success','Informations intégrées à la fiche client');
  157. },true);
  158. },true);
  159. }
  160. //Enregistrement des configurations
  161. function client_setting_save(){
  162. $.action({
  163. action: 'client_setting_save',
  164. fields: $('#client-setting-form').toJson()
  165. },function(){
  166. $.message('success','Enregistré');
  167. });
  168. }
  169. /** CLIENT **/
  170. //Récuperation d'une liste de client dans le tableau #clients
  171. function client_client_search(options){
  172. options = !options ? {} : options;
  173. var box = new FilterBox('#filters');
  174. if(options && options.exportMode) $('.btn-export').addClass('btn-preloader');
  175. var searchTable = $('#clients').data('searchTable');
  176. searchTable.resetGlobalCheckbox();
  177. if(!options.keepChecked) searchTable.resetCheckbox();
  178. $('#clients').fill({
  179. action:'client_client_search',
  180. filters: box.filters(),
  181. sort: $('#clients').sortable_table('get'),
  182. firm: $.urlParam('firm'),
  183. export: !options.exportMode ? false : options.exportMode,
  184. selected : searchTable.checkboxes()
  185. },function(response){
  186. if(!options.exportMode) $('.results-count > span').text(response.pagination.total);
  187. searchTable.fillCheckbox();
  188. if(options.callback!=null) options.callback(response);
  189. init_components();
  190. });
  191. }
  192. function client_client_mail_copy(){
  193. $.action({
  194. action : 'client_client_mail_copy',
  195. ids : $('#clients').data('searchTable').checkboxes()
  196. },function(r){
  197. copy_string(r.mails.join(';'));
  198. $.message('success',r.mails.length+' e-mail copiés');
  199. });
  200. }
  201. function client_relation_search(callback){
  202. $('#holding').html('');
  203. $('#subsites').fill({
  204. action:'client_relation_search',
  205. client: $.urlParam('id'),
  206. showing:function(line,key,data){
  207. if(data.level == 'holding'){
  208. $('#holding').append(line.detach());
  209. }else if(data.level =='memberof'){
  210. $('#memberof').append(line.detach());
  211. }
  212. line.removeClass('hidden');
  213. }
  214. },function(response){
  215. var count = $('#subsites .site-block:visible').length;
  216. $('.client-subsite-count').text(count>0?'('+count+') ':'');
  217. if(callback!=null) callback();
  218. });
  219. }
  220. function client_relation_add(modal){
  221. var site = $.urlParam('id');
  222. if(!modal){
  223. $.action({
  224. action : 'client_relation_add',
  225. relation : $('#relation-link').val(),
  226. id : site,
  227. level : $('[name="relation-level"]:checked').val()
  228. },function(r){
  229. client_relation_search();
  230. });
  231. $('#client-holding-modal').modal('hide');
  232. }else{
  233. if(!site) return $.message('error','Vous ne pouvez lié le client qu\'une fois celui çi enregistré');
  234. $('#client-holding-modal').modal('show');
  235. }
  236. }
  237. function client_relation_delete(element){
  238. var line = $(element).closest('.site-block');
  239. if(!confirm('Êtes-vous sûr de vouloir supprimer cette relation ?')) return;
  240. $.action({
  241. action : 'client_relation_delete',
  242. relation : line.attr('data-id'),
  243. id : $.urlParam('id'),
  244. level : line.attr('data-level')
  245. },function(r){
  246. line.remove();
  247. });
  248. $('#client-holding-modal').modal('hide');
  249. }
  250. //Ajout ou modification d'élément client
  251. function client_client_save(callback,noMessage){
  252. var data = $('#client-form').toJson();
  253. data.type = $('input[name="type"]:checked').val();
  254. $('#client-form input[type="radio"]:checked').each(function(i,element){
  255. data[$(element).attr('name')] = $(element).attr('value');
  256. });
  257. $('#client-form input[type="checkbox"]').each(function(i,element){
  258. data[$(element).attr('id')] = $(element).prop('checked') ? 1 : 0;
  259. });
  260. data.address = $('#address').data();
  261. data.id = $('.client-container').attr('data-id');
  262. data.logo = $('#logo-thumbnail').get(0).files[0];
  263. data.cover = $('#cover-thumbnail').get(0).files[0];
  264. data.parent = $.urlParam('parent');
  265. $.action(data,function(r){
  266. $.urlParam('id',r.id)
  267. $('.client-container').attr('data-id',r.id);
  268. if(callback) callback(r);
  269. if(!noMessage) $.message('success','Enregistré');
  270. });
  271. }
  272. //Fusion d'un client avec un autre (modale)
  273. function client_client_merge_edit(){
  274. $('#client-merge-modal').modal('show');
  275. $('.btn-merge').removeClass('hidden');
  276. }
  277. //Fusion d'un client avec un autre (execution)
  278. function client_client_merge(){
  279. if(!confirm('Êtes-vous sûr de vouloir fusionner ces clients ? Cette opération est irréversible')) return;
  280. $('.btn-merge').addClass('hidden');
  281. var data = { action : 'client_client_merge'};
  282. data.left = $('.client-container').attr('data-id');
  283. data.right = $('#client-merge-right').val();
  284. data.keep = {};
  285. $('#client-merge-modal input[type="radio"]:checked').each(function(){
  286. data.keep[$(this).attr('data-key')] = $(this).val();
  287. });
  288. $.action(data,function(r){
  289. $('#client-merge-modal .merge-logs').html(r.logs.join('<br>'));
  290. $.message('success','Client fusionné');
  291. });
  292. }
  293. //Vérification des doublons
  294. function client_client_check_duplicate(element){
  295. element = $(element);
  296. $.action({
  297. action : 'client_client_check_duplicate',
  298. field : element.attr('id'),
  299. label : element.val(),
  300. id : $('#client-form').attr('data-id')
  301. },function(r){
  302. var clientWarning = $('.client-warning',element.parent());
  303. if(clientWarning.length==0){
  304. clientWarning = $('<a class="input-group-append hidden client-warning" data-tooltip> \
  305. <span class="btn pr-0"><i class="fas fa-exclamation-circle text-warning"></i></span></a>');
  306. element.after(clientWarning);
  307. }
  308. var filters = {"k":"","a":[]}
  309. if(r.rows.length>0){
  310. var title = r.rows.length+' client(s) existant(s) montre(nt) des similarités avec ce champ'+"<br>";
  311. for(var k in r.rows){
  312. var row = r.rows[k];
  313. var filter = {"t":"number","c":"main.id","o":"=","v":[row.id]};
  314. if(k != r.rows.length-1) filter.j = "or";
  315. filters.a.push(filter);
  316. title += '- '+row.label+' (#'+row.id+')'+"<br>";
  317. }
  318. var url = 'index.php?module=client&p=1&filters='+btoa(JSON.stringify(filters));
  319. clientWarning.removeClass('hidden').attr('title',title).attr('href',url);
  320. init_components(clientWarning.parent());
  321. }else{
  322. clientWarning.addClass('hidden');
  323. }
  324. });
  325. }
  326. //Suppression d'élement client
  327. function client_client_delete(element){
  328. if(!confirm('Êtes vous sûr de vouloir supprimer ce client ?')) return;
  329. var recursive = confirm('Voulez vous supprimer également les sous entreprises de ce client ?');
  330. var line = element ? $(element).closest('tr') : null;
  331. var id = line ? line.attr('data-id') : $.urlParam('id');
  332. $.action({
  333. action: 'client_client_delete',
  334. id: id,
  335. recursive : recursive ?1:0
  336. },function(r){
  337. if(line){
  338. client_client_search();
  339. $.message('success','Client supprimé');
  340. }else{
  341. window.location = 'index.php?module=client&success=Client%20supprimé';
  342. }
  343. });
  344. }
  345. /** CLIENTCONTACT **/
  346. //Récuperation d'une liste de clientcontact dans le tableau #clientcontacts
  347. function client_contact_search(callback,exportMode){
  348. $.action({
  349. action:'client_contact_search',
  350. client: $.urlParam('id')
  351. },function(response){
  352. var tpl = $('.client-contact-panel .contact-template').get(0).outerHTML;
  353. $('#internals li:visible,#contacts li:visible').remove();
  354. var stats = {contacts :0,internals :0,}
  355. for (var k in response.rows) {
  356. var data = response.rows[k];
  357. var li = $(Mustache.render(tpl,data));
  358. li.removeClass('hidden');
  359. if(data.type=='user'){
  360. $('#internals').append(li);
  361. stats.internals++;
  362. }else{
  363. $('#contacts').append(li);
  364. stats.contacts++;
  365. }
  366. }
  367. $('.internals-title span').text(stats.internals);
  368. $('.contacts-title span').text(stats.contacts);
  369. });
  370. }
  371. function client_contact_mobile_toggle(){
  372. $('.client-contact-panel').toggle();
  373. client_update_map_size();
  374. }
  375. //Ajout ou modification d'élément clientcontact
  376. function client_contact_save(){
  377. var data = $('#contactModal').toJson();
  378. data.action = 'client_contact_save';
  379. data.client = $.urlParam('id');
  380. data.id = $('#contactModal').attr('data-id');
  381. data.account = $('#contactModal .contact-type-block:not(.hidden) [data-id="account"]').val();
  382. data.job = data['contact-job'];
  383. data.comment = data['contact-comment'];
  384. data.mail = data['contact-mail'];
  385. data.phone = data['contact-phone'];
  386. data.mobile = data['contact-mobile'];
  387. data.type = $('[name="contact-type"]:checked').attr('data-value');
  388. $.action(data,function(r){
  389. $.message('success','Enregistré');
  390. $('#contactModal').clear().modal('hide');
  391. client_contact_search();
  392. });
  393. }
  394. function client_contact_edit(element){
  395. var id = element ? $(element).closest('li').attr('data-id'): null;
  396. var modal = $('#contactModal');
  397. modal.clear();
  398. $.action({
  399. action: 'client_contact_edit',
  400. id: id
  401. },function(r){
  402. r['contact-job'] = r.job;
  403. r['contact-comment'] = r.comment;
  404. r['contact-phone'] = r.phone;
  405. r['contact-mobile'] = r.mobile;
  406. r['contact-mail'] = r.mail;
  407. $.setForm('#contactModal',r);
  408. $('#civility option[value="'+r.civility+'"]').prop('selected',true);
  409. modal.modal('show');
  410. modal.attr('data-id',r.id);
  411. if(!r.type) r.type = 'external';
  412. $('[name="contact-type"][data-value="'+r.type+'"]').click();
  413. client_contact_type();
  414. init_components('#contactModal');
  415. });
  416. }
  417. //Suppression d'élement clientcontact
  418. function client_contact_delete(element){
  419. if(!confirm('Êtes vous sûr de vouloir supprimer ce contact ?')) return;
  420. var line = $(element).closest('li');
  421. $.action({
  422. action: 'client_contact_delete',
  423. id: line.attr('data-id')
  424. },function(r){
  425. line.remove();
  426. $.message('info','Contact supprimé');
  427. });
  428. }
  429. function client_contact_type(){
  430. $('.contact-type-block').addClass('hidden');
  431. switch($('[name="contact-type"]:checked').attr('data-value')){
  432. case 'external':
  433. $('.external-type-block').removeClass('hidden');
  434. break;
  435. case 'client':
  436. $('.client-type-block').removeClass('hidden');
  437. break;
  438. case 'user':
  439. $('.user-type-block').removeClass('hidden');
  440. break;
  441. }
  442. }
  443. //Gestion des adresses
  444. function client_address_search(callback,exportMode){
  445. $.action({
  446. action:'client_address_search',
  447. client: $.urlParam('id')
  448. },function(response){
  449. var tpl = $('.client-contact-panel .address.hidden').get(0).outerHTML;
  450. $('#addresses li:visible').remove();
  451. for (var k in response.rows) {
  452. var data = response.rows[k];
  453. var li = $(Mustache.render(tpl,data));
  454. li.removeClass('hidden');
  455. $('#addresses').append(li);
  456. }
  457. if(response.rows) $('.address-title span').text(response.rows.length);
  458. if(callback!=null) callback();
  459. });
  460. }
  461. function client_address_save(fromCode,callback,noMessage){
  462. var data = $('#addressModal').toJson();
  463. data.action = 'client_address_save';
  464. data.client = $.urlParam('id');
  465. data.id = $('#addressModal').attr('data-id');
  466. data.job = data['contact-job'];
  467. data.mail = data['contact-mail'];
  468. data.phone = data['contact-phone'];
  469. for(var k in data){
  470. data[k.replace('address-','')] = data[k];
  471. }
  472. if(fromCode) $.extend(data,fromCode);
  473. $.action(data,function(r){
  474. if(!noMessage) $.message('success','Enregistré');
  475. if(callback) callback();
  476. $('#addressModal').clear().modal('hide');
  477. client_address_search(function(){
  478. client_address_change();
  479. });
  480. });
  481. }
  482. function client_address_edit(element){
  483. var id = element ? $(element).closest('li').attr('data-id'): null;
  484. $('#addressModal').modal('show');
  485. $('#addressModal').clear();
  486. if(id){
  487. $.action({
  488. action: 'client_address_edit',
  489. id: id
  490. },function(r){
  491. $('#address-type').val(r.type);
  492. $('#address-street').val(r.street);
  493. $('#address-complement').val(r.complement);
  494. $('#address-zip').val(r.zip);
  495. $('#address-city').val(r.city);
  496. $('#address-country').val(r.country);
  497. $('#addressModal').attr('data-id',r.id);
  498. init_components('#addressModal');
  499. });
  500. }
  501. }
  502. function client_address_fill(data){
  503. $('#address-street').val(data.address);
  504. $('#address-zip').val(data.zip);
  505. $('#address-city').val(data.city);
  506. $('#address-country').val(data.country);
  507. }
  508. function client_address_delete(element){
  509. if(!confirm('Êtes-vous sûr de vouloir supprimer cette adresse ?')) return;
  510. var line = $(element).closest('li');
  511. $.action({
  512. action: 'client_address_delete',
  513. id: line.attr('data-id')
  514. },function(r){
  515. line.remove();
  516. $.message('info','Adresse supprimée');
  517. });
  518. }
  519. function client_address_copy(element){
  520. var line = $(element).closest('li');
  521. var datas = ['street', 'complement', 'zip', 'city', 'country'];
  522. var address = [];
  523. datas.forEach(function(data){
  524. var attribute = line.attr('data-'+data);
  525. if (attribute) address.push(attribute);
  526. });
  527. var clipboard = address.join(', ');
  528. copy_string(clipboard);
  529. $.message('success','Copié avec succès');
  530. }
  531. /** HISTORY **/
  532. //Récuperation d'une liste de history dans le tableau #historys
  533. function client_core_history_search(callback,exportMode){
  534. if($('.client-container').attr('data-id')=='') return;
  535. var box = new FilterBox('#client-history-filters');
  536. $('#historys').fill({
  537. action:'client_core_history_search',
  538. filters: box.filters(),
  539. id: $('.client-container').attr('data-id'),
  540. export: !exportMode ? false : exportMode
  541. },function(response){
  542. $('.results-count span').text(response.pagination.total);
  543. if(callback!=null) callback();
  544. });
  545. }
  546. function client_core_history_save(callback){
  547. var data = {action:'client_core_history_save',client:$.urlParam('id'),comment:$('#history-comment').val()}
  548. if($('#history-comment').attr('data-id')) data.id = $('#history-comment').attr('data-id');
  549. $.action(data,function(r){
  550. $('#history-comment').attr('data-id','')
  551. $('#history-comment').val('');
  552. $('#history-comment').data('trumbowyg').empty()
  553. client_core_history_search();
  554. if(callback) callback();
  555. });
  556. }
  557. function client_history_edit(element){
  558. var line = $(element).closest('.item-line');
  559. console.log(line,element);
  560. $.action({
  561. action: 'client_history_edit',
  562. id: line.attr('data-id')
  563. },function(r){
  564. $('#history-comment').val(r.comment).attr('data-id',r.id);
  565. init_components($('#history-comment').parent());
  566. });
  567. }
  568. function client_core_history_delete(element){
  569. if(!confirm('Êtes-vous sûr de vouloir supprimer cet historique client ?')) return;
  570. var line = $(element).closest('.item-line');
  571. $.action({
  572. action: 'client_core_history_delete',
  573. id: line.attr('data-id')
  574. },function(r){
  575. line.remove();
  576. });
  577. }
  578. function client_update_map_size(){
  579. var height = $('.client-info').outerHeight();
  580. $('.client-map').css('height',height+'px');
  581. $('#gmap_canvas')
  582. .attr('width',$('.client-map').outerWidth())
  583. .attr('height',height);
  584. }