mailbox.js 91 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455
  1. $(document).ready(function() {
  2. acl_data = JSON.parse(acl);
  3. // Set paging
  4. // Clone mailbox mass actions
  5. $("div").find("[data-actions-header='true'").each(function() {
  6. $(this).html($(this).nextAll('.mass-actions-mailbox:first').html());
  7. });
  8. // Auto-fill domain quota when adding new domain
  9. auto_fill_quota = function(domain) {
  10. $.get("/api/v1/get/domain/" + domain, function(data){
  11. var result = $.parseJSON(JSON.stringify(data));
  12. def_new_mailbox_quota = ( result.def_new_mailbox_quota / 1048576);
  13. max_new_mailbox_quota = ( result.max_new_mailbox_quota / 1048576);
  14. if (max_new_mailbox_quota != '0') {
  15. $('.addInputQuotaExhausted').hide();
  16. $("#quotaBadge").html('max. ' + max_new_mailbox_quota + ' MiB');
  17. $('#addInputQuota').attr({"disabled": false, "value": "", "type": "number", "max": max_new_mailbox_quota});
  18. $('#addInputQuota').val(def_new_mailbox_quota);
  19. }
  20. else {
  21. $('.addInputQuotaExhausted').show();
  22. $("#quotaBadge").html('max. ' + max_new_mailbox_quota + ' MiB');
  23. $('#addInputQuota').attr({"disabled": true, "value": "", "type": "text", "value": "n/a"});
  24. $('#addInputQuota').val(max_new_mailbox_quota);
  25. }
  26. });
  27. }
  28. $('#addSelectDomain').on('change', function() {
  29. auto_fill_quota($('#addSelectDomain').val());
  30. });
  31. auto_fill_quota($('#addSelectDomain').val());
  32. $(".goto_checkbox").click(function( event ) {
  33. $("form[data-id='add_alias'] .goto_checkbox").not(this).prop('checked', false);
  34. if ($("form[data-id='add_alias'] .goto_checkbox:checked").length > 0) {
  35. $('#textarea_alias_goto').prop('disabled', true);
  36. }
  37. else {
  38. $("#textarea_alias_goto").removeAttr('disabled');
  39. }
  40. });
  41. $('#addAliasModal').on('show.bs.modal', function(e) {
  42. if ($("form[data-id='add_alias'] .goto_checkbox:checked").length > 0) {
  43. $('#textarea_alias_goto').prop('disabled', true);
  44. }
  45. else {
  46. $("#textarea_alias_goto").removeAttr('disabled');
  47. }
  48. });
  49. // Log modal
  50. $('#syncjobLogModal').on('show.bs.modal', function(e) {
  51. var syncjob_id = $(e.relatedTarget).data('syncjob-id');
  52. $.ajax({
  53. url: '/inc/ajax/syncjob_logs.php',
  54. data: { id: syncjob_id },
  55. dataType: 'text',
  56. success: function(data){
  57. $(e.currentTarget).find('#logText').text(data);
  58. },
  59. error: function(xhr, status, error) {
  60. $(e.currentTarget).find('#logText').text(xhr.responseText);
  61. }
  62. });
  63. });
  64. // Log modal
  65. $('#dnsInfoModal').on('show.bs.modal', function(e) {
  66. var domain = $(e.relatedTarget).data('domain');
  67. $('.dns-modal-body').html('<div class="spinner-border" role="status"><span class="visually-hidden">Loading...</span></div>');
  68. $.ajax({
  69. url: '/inc/ajax/dns_diagnostics.php',
  70. data: { domain: domain },
  71. dataType: 'text',
  72. success: function(data){
  73. $('.dns-modal-body').html(data);
  74. },
  75. error: function(xhr, status, error) {
  76. $('.dns-modal-body').html(xhr.responseText);
  77. }
  78. });
  79. });
  80. // @Open Domain add modal
  81. $('#addDomainModal').on('show.bs.modal', function(e) {
  82. $.ajax({
  83. url: '/api/v1/get/domain/template/all',
  84. data: {},
  85. dataType: 'json',
  86. success: async function(data){
  87. $('#domain_templates').find('option').remove();
  88. $('#domain_templates').selectpicker('destroy');
  89. $('#domain_templates').selectpicker();
  90. for (var i = 0; i < data.length; i++){
  91. if (data[i].template === "Default"){
  92. $('#domain_templates').prepend($('<option>', {
  93. 'value': data[i].id,
  94. 'text': data[i].template,
  95. 'data-attributes': JSON.stringify(data[i].attributes),
  96. 'selected': true
  97. }));
  98. setDomainTemplateData(data[i].attributes);
  99. } else {
  100. $('#domain_templates').append($('<option>', {
  101. 'value': data[i].id,
  102. 'text': data[i].template,
  103. 'data-attributes': JSON.stringify(data[i].attributes),
  104. 'selected': false
  105. }));
  106. }
  107. };
  108. $('#domain_templates').selectpicker("refresh");
  109. // @selecting template
  110. $('#domain_templates').on('change', function(){
  111. var selected = $('#domain_templates option:selected');
  112. var attr = selected.data('attributes');
  113. setDomainTemplateData(attr);
  114. });
  115. },
  116. error: function(xhr, status, error) {
  117. console.log(error);
  118. }
  119. });
  120. });
  121. // @Open Mailbox add modal
  122. $('#addMailboxModal').on('show.bs.modal', function(e) {
  123. $.ajax({
  124. url: '/api/v1/get/mailbox/template/all',
  125. data: {},
  126. dataType: 'json',
  127. success: async function(data){
  128. $('#mailbox_templates').find('option').remove();
  129. $('#mailbox_templates').selectpicker('destroy');
  130. $('#mailbox_templates').selectpicker();
  131. for (var i = 0; i < data.length; i++){
  132. if (data[i].template === "Default"){
  133. $('#mailbox_templates').prepend($('<option>', {
  134. 'value': data[i].id,
  135. 'text': data[i].template,
  136. 'data-attributes': JSON.stringify(data[i].attributes),
  137. 'selected': true
  138. }));
  139. setMailboxTemplateData(data[i].attributes);
  140. } else {
  141. $('#mailbox_templates').append($('<option>', {
  142. value: data[i].id,
  143. text : data[i].template,
  144. 'data-attributes': JSON.stringify(data[i].attributes),
  145. 'selected': false
  146. }));
  147. }
  148. };
  149. $('#mailbox_templates').selectpicker("refresh");
  150. // @selecting template
  151. $('#mailbox_templates').on('change', function(){
  152. var selected = $('#mailbox_templates option:selected');
  153. var attr = selected.data('attributes');
  154. setMailboxTemplateData(attr);
  155. });
  156. },
  157. error: function(xhr, status, error) {
  158. console.log(error);
  159. }
  160. });
  161. });
  162. // @selecting identity provider mbox_add_modal
  163. $('#mbox_add_iam').on('change', function(){
  164. // toggle password fields
  165. if (this.value === 'mailcow'){
  166. $('#mbox_add_pwds').removeClass('d-none');
  167. $('#mbox_add_pwds').find('.form-control').prop('required', true);
  168. } else {
  169. $('#mbox_add_pwds').addClass('d-none');
  170. $('#mbox_add_pwds').find('.form-control').prop('required', false);
  171. }
  172. });
  173. // Sieve data modal
  174. $('#sieveDataModal').on('show.bs.modal', function(e) {
  175. var sieveScript = $(e.relatedTarget).data('sieve-script');
  176. $(e.currentTarget).find('#sieveDataText').html('<pre style="font-size:14px;line-height:1.1">' + sieveScript + '</pre>');
  177. });
  178. // Disable submit button on script change
  179. $('.textarea-code').on('keyup', function() {
  180. // Disable all "save" buttons, could be a "related button only" function, todo
  181. $('.add_sieve_script').attr({"disabled": true});
  182. });
  183. // Validate script data
  184. $(".validate_sieve").click(function( event ) {
  185. event.preventDefault();
  186. var validation_button = $(this);
  187. // Get script_data textarea content from form the button was clicked in
  188. var script = $('textarea[name="script_data"]', $(this).parents('form:first')).val();
  189. $.ajax({
  190. dataType: 'json',
  191. url: "/inc/ajax/sieve_validation.php",
  192. type: "get",
  193. data: { script: script },
  194. complete: function(data) {
  195. var response = (data.responseText);
  196. response_obj = JSON.parse(response);
  197. if (response_obj.type == "success") {
  198. $(validation_button).next().attr({"disabled": false});
  199. }
  200. mailcow_alert_box(response_obj.msg, response_obj.type);
  201. },
  202. });
  203. });
  204. // $(document).on('DOMNodeInserted', '#prefilter_table', function () {
  205. // $("#active-script").closest('td').css('background-color','#b0f0a0');
  206. // $("#inactive-script").closest('td').css('background-color','#b0f0a0');
  207. // });
  208. $('#addResourceModal').on('shown.bs.modal', function() {
  209. $("#multiple_bookings").val($("#multiple_bookings_select").val());
  210. if ($("#multiple_bookings").val() == "custom") {
  211. $("#multiple_bookings_custom_div").show();
  212. $("#multiple_bookings").val($("#multiple_bookings_custom").val());
  213. }
  214. })
  215. $("#multiple_bookings_select").change(function() {
  216. $("#multiple_bookings").val($("#multiple_bookings_select").val());
  217. if ($("#multiple_bookings").val() == "custom") {
  218. $("#multiple_bookings_custom_div").show();
  219. }
  220. else {
  221. $("#multiple_bookings_custom_div").hide();
  222. }
  223. });
  224. $("#multiple_bookings_custom").bind ("change keypress keyup blur", function () {
  225. $("#multiple_bookings").val($("#multiple_bookings_custom").val());
  226. });
  227. function setDomainTemplateData(template){
  228. $("#addDomain_max_aliases").val(template.max_num_aliases_for_domain);
  229. $("#addDomain_max_mailboxes").val(template.max_num_mboxes_for_domain);
  230. $("#addDomain_mailbox_quota_def").val(template.def_quota_for_mbox / 1048576);
  231. $("#addDomain_mailbox_quota_m").val(template.max_quota_for_mbox / 1048576);
  232. $("#addDomain_domain_quota_m").val(template.max_quota_for_domain / 1048576);
  233. if (template.gal == 1){
  234. $('#addDomain_gal').prop('checked', true);
  235. } else {
  236. $('#addDomain_gal').prop('checked', false);
  237. }
  238. if (template.active == 1){
  239. $('#addDomain_active').prop('checked', true);
  240. } else {
  241. $('#addDomain_active').prop('checked', false);
  242. }
  243. $("#addDomain_rl_value").val(template.rl_value);
  244. $('#addDomain_rl_frame').selectpicker('val', template.rl_frame);
  245. $("#dkim_selector").val(template.dkim_selector);
  246. if (!template.key_size)
  247. template.key_size = 2048;
  248. $('#key_size').selectpicker('val', template.key_size.toString());
  249. if (template.backupmx == 1){
  250. $('#addDomain_relay_domain').prop('checked', true);
  251. } else {
  252. $('#addDomain_relay_domain').prop('checked', false);
  253. }
  254. if (template.relay_all_recipients == 1){
  255. $('#addDomain_relay_all').prop('checked', true);
  256. } else {
  257. $('#addDomain_relay_all').prop('checked', false);
  258. }
  259. if (template.relay_unknown_only == 1){
  260. $('#addDomain_relay_unknown_only').prop('checked', true);
  261. } else {
  262. $('#addDomain_relay_unknown_only').prop('checked', false);
  263. }
  264. // load tags
  265. $('#addDomain_tags').val("");
  266. $($('#addDomain_tags').parent().find(".tag-values")[0]).val("");
  267. $('#addDomain_tags').parent().find(".tag-badge").remove();
  268. for (var i = 0; i < template.tags.length; i++)
  269. addTag($('#addDomain_tags'), template.tags[i]);
  270. }
  271. function setMailboxTemplateData(template){
  272. $("#addInputQuota").val(template.quota / 1048576);
  273. $('#mbox_add_iam').selectpicker('val', template.authsource);
  274. // toggle password fields
  275. if (template.authsource === 'mailcow'){
  276. $('#mbox_add_pwds').removeClass('d-none');
  277. $('#mbox_add_pwds').find('.form-control').prop('required', true);
  278. } else {
  279. $('#mbox_add_pwds').addClass('d-none');
  280. $('#mbox_add_pwds').find('.form-control').prop('required', false);
  281. }
  282. if (template.quarantine_notification === "never"){
  283. $('#quarantine_notification_never').prop('checked', true);
  284. $('#quarantine_notification_hourly').prop('checked', false);
  285. $('#quarantine_notification_daily').prop('checked', false);
  286. $('#quarantine_notification_weekly').prop('checked', false);
  287. } else if(template.quarantine_notification === "hourly"){
  288. $('#quarantine_notification_never').prop('checked', false);
  289. $('#quarantine_notification_hourly').prop('checked', true);
  290. $('#quarantine_notification_daily').prop('checked', false);
  291. $('#quarantine_notification_weekly').prop('checked', false);
  292. } else if(template.quarantine_notification === "daily"){
  293. $('#quarantine_notification_never').prop('checked', false);
  294. $('#quarantine_notification_hourly').prop('checked', false);
  295. $('#quarantine_notification_daily').prop('checked', true);
  296. $('#quarantine_notification_weekly').prop('checked', false);
  297. } else if(template.quarantine_notification === "weekly"){
  298. $('#quarantine_notification_never').prop('checked', false);
  299. $('#quarantine_notification_hourly').prop('checked', false);
  300. $('#quarantine_notification_daily').prop('checked', false);
  301. $('#quarantine_notification_weekly').prop('checked', true);
  302. } else {
  303. $('#quarantine_notification_never').prop('checked', false);
  304. $('#quarantine_notification_hourly').prop('checked', false);
  305. $('#quarantine_notification_daily').prop('checked', false);
  306. $('#quarantine_notification_weekly').prop('checked', false);
  307. }
  308. if (template.quarantine_category === "reject"){
  309. $('#quarantine_category_reject').prop('checked', true);
  310. $('#quarantine_category_add_header').prop('checked', false);
  311. $('#quarantine_category_all').prop('checked', false);
  312. } else if(template.quarantine_category === "add_header"){
  313. $('#quarantine_category_reject').prop('checked', false);
  314. $('#quarantine_category_add_header').prop('checked', true);
  315. $('#quarantine_category_all').prop('checked', false);
  316. } else if(template.quarantine_category === "all"){
  317. $('#quarantine_category_reject').prop('checked', false);
  318. $('#quarantine_category_add_header').prop('checked', false);
  319. $('#quarantine_category_all').prop('checked', true);
  320. }
  321. if (template.tls_enforce_in == 1){
  322. $('#tls_enforce_in').prop('checked', true);
  323. } else {
  324. $('#tls_enforce_in').prop('checked', false);
  325. }
  326. if (template.tls_enforce_out == 1){
  327. $('#tls_enforce_out').prop('checked', true);
  328. } else {
  329. $('#tls_enforce_out').prop('checked', false);
  330. }
  331. var protocol_access = [];
  332. if (template.imap_access == 1){
  333. protocol_access.push("imap");
  334. }
  335. if (template.pop3_access == 1){
  336. protocol_access.push("pop3");
  337. }
  338. if (template.smtp_access == 1){
  339. protocol_access.push("smtp");
  340. }
  341. if (template.sieve_access == 1){
  342. protocol_access.push("sieve");
  343. }
  344. $('#protocol_access').selectpicker('val', protocol_access);
  345. var acl = [];
  346. if (template.acl_spam_alias == 1){
  347. acl.push("spam_alias");
  348. }
  349. if (template.acl_tls_policy == 1){
  350. acl.push("tls_policy");
  351. }
  352. if (template.acl_spam_score == 1){
  353. acl.push("spam_score");
  354. }
  355. if (template.acl_spam_policy == 1){
  356. acl.push("spam_policy");
  357. }
  358. if (template.acl_delimiter_action == 1){
  359. acl.push("delimiter_action");
  360. }
  361. if (template.acl_syncjobs == 1){
  362. acl.push("syncjobs");
  363. }
  364. if (template.acl_eas_reset == 1){
  365. acl.push("eas_reset");
  366. }
  367. if (template.acl_sogo_profile_reset == 1){
  368. acl.push("sogo_profile_reset");
  369. }
  370. if (template.acl_pushover == 1){
  371. acl.push("pushover");
  372. }
  373. if (template.acl_quarantine == 1){
  374. acl.push("quarantine");
  375. }
  376. if (template.acl_quarantine_attachments == 1){
  377. acl.push("quarantine_attachments");
  378. }
  379. if (template.acl_quarantine_notification == 1){
  380. acl.push("quarantine_notification");
  381. }
  382. if (template.acl_quarantine_category == 1){
  383. acl.push("quarantine_category");
  384. }
  385. if (template.acl_app_passwds == 1){
  386. acl.push("app_passwds");
  387. }
  388. $('#user_acl').selectpicker('val', acl);
  389. $('#rl_value').val(template.rl_value);
  390. if (template.rl_frame){
  391. $('#rl_frame').selectpicker('val', template.rl_frame);
  392. }
  393. console.log(template.active)
  394. if (template.active){
  395. $('#mbox_active').selectpicker('val', template.active.toString());
  396. } else {
  397. $('#mbox_active').selectpicker('val', '');
  398. }
  399. if (template.force_pw_update == 1){
  400. $('#force_pw_update').prop('checked', true);
  401. } else {
  402. $('#force_pw_update').prop('checked', false);
  403. }
  404. if (template.sogo_access == 1){
  405. $('#sogo_access').prop('checked', true);
  406. } else {
  407. $('#sogo_access').prop('checked', false);
  408. }
  409. // load tags
  410. $('#addMailbox_tags').val("");
  411. $($('#addMailbox_tags').parent().find(".tag-values")[0]).val("");
  412. $('#addMailbox_tags').parent().find(".tag-badge").remove();
  413. for (var i = 0; i < template.tags.length; i++)
  414. addTag($('#addMailbox_tags'), template.tags[i]);
  415. }
  416. });
  417. jQuery(function($){
  418. // http://stackoverflow.com/questions/46155/validate-email-address-in-javascript
  419. function humanFileSize(i){if(Math.abs(i)<1024)return i+" B";var B=["KiB","MiB","GiB","TiB","PiB","EiB","ZiB","YiB"],e=-1;do{i/=1024,++e}while(Math.abs(i)>=1024&&e<B.length-1);return i.toFixed(1)+" "+B[e]}
  420. function unix_time_format(i){return""==i?'<i class="bi bi-x"></i>':new Date(i?1e3*i:0).toLocaleDateString(void 0,{year:"numeric",month:"2-digit",day:"2-digit",hour:"2-digit",minute:"2-digit",second:"2-digit"})}
  421. $(".refresh_table").on('click', function(e) {
  422. e.preventDefault();
  423. var table_name = $(this).data('table');
  424. if ($.fn.DataTable.isDataTable('#' + table_name))
  425. $('#' + table_name).DataTable().ajax.reload();
  426. });
  427. function draw_domain_table() {
  428. // just recalc width if instance already exists
  429. if ($.fn.DataTable.isDataTable('#domain_table') ) {
  430. $('#domain_table').DataTable().columns.adjust().responsive.recalc();
  431. return;
  432. }
  433. var table = $('#domain_table').DataTable({
  434. responsive: true,
  435. processing: true,
  436. serverSide: true,
  437. stateSave: true,
  438. pageLength: pagination_size,
  439. dom: "<'row'<'col-sm-12 col-md-6'f><'col-sm-12 col-md-6'l>>" +
  440. "tr" +
  441. "<'row'<'col-sm-12 col-md-5'i><'col-sm-12 col-md-7'p>>",
  442. language: lang_datatables,
  443. initComplete: function(){
  444. hideTableExpandCollapseBtn('#tab-domains', '#domain_table');
  445. },
  446. ajax: {
  447. type: "GET",
  448. url: "/api/v1/get/domain/datatables",
  449. dataSrc: function(json){
  450. $.each(json.data, function(i, item) {
  451. item.domain_name = escapeHtml(item.domain_name);
  452. item.aliases = item.aliases_in_domain + " / " + item.max_num_aliases_for_domain;
  453. item.mailboxes = item.mboxes_in_domain + " / " + item.max_num_mboxes_for_domain;
  454. item.quota = item.quota_used_in_domain + "/" + item.max_quota_for_domain + "/" + item.bytes_total;
  455. item.stats = item.msgs_total + "/" + item.bytes_total;
  456. if (!item.rl) item.rl = '∞';
  457. else {
  458. item.rl = $.map(item.rl, function(e){
  459. return e;
  460. }).join('/1');
  461. }
  462. item.def_quota_for_mbox = humanFileSize(item.def_quota_for_mbox);
  463. item.max_quota_for_mbox = humanFileSize(item.max_quota_for_mbox);
  464. item.chkbox = '<input type="checkbox" class="form-check-input" data-id="domain" name="multi_select" value="' + encodeURIComponent(item.domain_name) + '" />';
  465. item.action = '<div class="btn-group">';
  466. if (role == "admin") {
  467. item.action += '<a href="/edit/domain/' + encodeURIComponent(item.domain_name) + '" class="btn btn-sm btn-xs-lg btn-xs-half btn-secondary"><i class="bi bi-pencil-fill"></i> ' + lang.edit + '</a>' +
  468. '<a href="#" data-action="delete_selected" data-id="single-domain" data-api-url="delete/domain" data-item="' + encodeURIComponent(item.domain_name) + '" class="btn btn-sm btn-xs-lg btn-xs-half btn-danger"><i class="bi bi-trash"></i> ' + lang.remove + '</a>' +
  469. '<a href="#dnsInfoModal" class="btn btn-sm btn-xs-lg btn-info" data-bs-toggle="modal" data-domain="' + encodeURIComponent(item.domain_name) + '"><i class="bi bi-globe2"></i> DNS</a></div>';
  470. }
  471. else {
  472. item.action += '<a href="/edit/domain/' + encodeURIComponent(item.domain_name) + '" class="btn btn-sm btn-xs-lg btn-xs-half btn-secondary"><i class="bi bi-pencil-fill"></i> ' + lang.edit + '</a>' +
  473. '<a href="#dnsInfoModal" class="btn btn-sm btn-xs-lg btn-xs-half btn-info" data-bs-toggle="modal" data-domain="' + encodeURIComponent(item.domain_name) + '"><i class="bi bi-globe2"></i> DNS</a></div>';
  474. }
  475. if (Array.isArray(item.tags)){
  476. var tags = '';
  477. for (var i = 0; i < item.tags.length; i++)
  478. tags += '<span class="badge bg-primary tag-badge"><i class="bi bi-tag-fill"></i> ' + escapeHtml(item.tags[i]) + '</span>';
  479. item.tags = tags;
  480. } else {
  481. item.tags = '';
  482. }
  483. if (item.backupmx == 1) {
  484. if (item.relay_unknown_only == 1) {
  485. item.domain_name = '<div class="badge fs-6 bg-info">Relay Non-Local</div> ' + item.domain_name;
  486. } else if (item.relay_all_recipients == 1) {
  487. item.domain_name = '<div class="badge fs-6 bg-info">Relay All</div> ' + item.domain_name;
  488. } else {
  489. item.domain_name = '<div class="badge fs-6 bg-info">Relay</div> ' + item.domain_name;
  490. }
  491. }
  492. });
  493. return json.data;
  494. }
  495. },
  496. columns: [
  497. {
  498. // placeholder, so checkbox will not block child row toggle
  499. title: '',
  500. data: null,
  501. searchable: false,
  502. orderable: false,
  503. defaultContent: '',
  504. responsivePriority: 1
  505. },
  506. {
  507. title: '',
  508. data: 'chkbox',
  509. searchable: false,
  510. orderable: false,
  511. defaultContent: '',
  512. responsivePriority: 2
  513. },
  514. {
  515. title: lang.domain,
  516. data: 'domain_name',
  517. responsivePriority: 3,
  518. defaultContent: ''
  519. },
  520. {
  521. title: lang.aliases,
  522. data: 'aliases',
  523. searchable: false,
  524. defaultContent: ''
  525. },
  526. {
  527. title: lang.mailboxes,
  528. data: 'mailboxes',
  529. searchable: false,
  530. responsivePriority: 4,
  531. defaultContent: ''
  532. },
  533. {
  534. title: lang.domain_quota,
  535. data: 'quota',
  536. searchable: false,
  537. defaultContent: '',
  538. render: function (data, type) {
  539. data = data.split("/");
  540. return humanFileSize(data[0]) + " / " + humanFileSize(data[1]);
  541. }
  542. },
  543. {
  544. title: lang.stats,
  545. data: 'stats',
  546. searchable: false,
  547. defaultContent: '',
  548. render: function (data, type) {
  549. data = data.split("/");
  550. return '<i class="bi bi-files"></i> ' + data[0] + ' / ' + humanFileSize(data[1]);
  551. }
  552. },
  553. {
  554. title: lang.mailbox_defquota,
  555. data: 'def_quota_for_mbox',
  556. searchable: false,
  557. defaultContent: ''
  558. },
  559. {
  560. title: lang.mailbox_quota,
  561. data: 'max_quota_for_mbox',
  562. searchable: false,
  563. defaultContent: ''
  564. },
  565. {
  566. title: 'RL',
  567. data: 'rl',
  568. searchable: false,
  569. orderable: false,
  570. defaultContent: ''
  571. },
  572. {
  573. title: lang.backup_mx,
  574. data: 'backupmx',
  575. searchable: false,
  576. defaultContent: '',
  577. render: function (data, type){
  578. return 1==data ? '<i class="bi bi-check-lg"></i>' : 0==data && '<i class="bi bi-x-lg"></i>';
  579. }
  580. },
  581. {
  582. title: lang.domain_admins,
  583. data: 'domain_admins',
  584. searchable: false,
  585. orderable: false,
  586. defaultContent: '',
  587. className: 'none'
  588. },
  589. {
  590. title: lang.created_on,
  591. data: 'created',
  592. searchable: false,
  593. orderable: false,
  594. defaultContent: '',
  595. className: 'none'
  596. },
  597. {
  598. title: lang.last_modified,
  599. data: 'modified',
  600. searchable: false,
  601. orderable: false,
  602. defaultContent: '',
  603. className: 'none'
  604. },
  605. {
  606. title: 'Tags',
  607. data: 'tags',
  608. searchable: true,
  609. orderable: false,
  610. defaultContent: '',
  611. className: 'none'
  612. },
  613. {
  614. title: lang.active,
  615. data: 'active',
  616. searchable: false,
  617. defaultContent: '',
  618. responsivePriority: 6,
  619. render: function (data, type) {
  620. return 1==data?'<i class="bi bi-check-lg"><span class="sorting-value">1</span></i>':(0==data?'<i class="bi bi-x-lg"><span class="sorting-value">0</span></i>':2==data&&'&#8212;');
  621. }
  622. },
  623. {
  624. title: lang.action,
  625. data: 'action',
  626. searchable: false,
  627. orderable: false,
  628. className: 'dt-sm-head-hidden dt-data-w100 dtr-col-md dt-text-right',
  629. responsivePriority: 5,
  630. defaultContent: ''
  631. },
  632. ]
  633. });
  634. table.on('responsive-resize', function (e, datatable, columns){
  635. hideTableExpandCollapseBtn('#tab-domains', '#domain_table');
  636. });
  637. }
  638. function draw_templates_domain_table() {
  639. // just recalc width if instance already exists
  640. if ($.fn.DataTable.isDataTable('#templates_domain_table') ) {
  641. $('#templates_domain_table').DataTable().columns.adjust().responsive.recalc();
  642. return;
  643. }
  644. var table = $('#templates_domain_table').DataTable({
  645. responsive: true,
  646. processing: true,
  647. serverSide: false,
  648. stateSave: true,
  649. pageLength: pagination_size,
  650. dom: "<'row'<'col-sm-12 col-md-6'f><'col-sm-12 col-md-6'l>>" +
  651. "tr" +
  652. "<'row'<'col-sm-12 col-md-5'i><'col-sm-12 col-md-7'p>>",
  653. language: lang_datatables,
  654. order: [[2, 'desc']],
  655. initComplete: function(){
  656. hideTableExpandCollapseBtn('#tab-templates-domains', '#templates_domain_table');
  657. },
  658. ajax: {
  659. type: "GET",
  660. url: "/api/v1/get/domain/template/all",
  661. dataSrc: function(json){
  662. $.each(json, function (i, item) {
  663. item.chkbox = '<input type="checkbox" class="form-check-input" data-id="domain_template" name="multi_select" value="' + encodeURIComponent(item.id) + '" />';
  664. item.attributes.def_quota_for_mbox = humanFileSize(item.attributes.def_quota_for_mbox);
  665. item.attributes.max_quota_for_mbox = humanFileSize(item.attributes.max_quota_for_mbox);
  666. item.attributes.max_quota_for_domain = humanFileSize(item.attributes.max_quota_for_domain);
  667. item.template = escapeHtml(item.template);
  668. if (item.attributes.rl_frame === "s"){
  669. item.attributes.rl_frame = lang_rl.second;
  670. } else if (item.attributes.rl_frame === "m"){
  671. item.attributes.rl_frame = lang_rl.minute;
  672. } else if (item.attributes.rl_frame === "h"){
  673. item.attributes.rl_frame = lang_rl.hour;
  674. } else if (item.attributes.rl_frame === "d"){
  675. item.attributes.rl_frame = lang_rl.day;
  676. }
  677. item.attributes.rl_value = escapeHtml(item.attributes.rl_value);
  678. if (item.template.toLowerCase() == "default"){
  679. item.action = '<div class="btn-group">' +
  680. '<a href="/edit/template/' + encodeURIComponent(item.id) + '" class="btn btn-sm btn-xs-lg btn-xs-half btn-secondary"><i class="bi bi-pencil-fill"></i> ' + lang.edit + '</a>' +
  681. '</div>';
  682. }
  683. else {
  684. item.action = '<div class="btn-group">' +
  685. '<a href="/edit/template/' + encodeURIComponent(item.id) + '" class="btn btn-sm btn-xs-lg btn-xs-half btn-secondary"><i class="bi bi-pencil-fill"></i> ' + lang.edit + '</a>' +
  686. '<a href="#" data-action="delete_selected" data-id="single-template" data-api-url="delete/domain/template" data-item="' + encodeURIComponent(item.id) + '" class="btn btn-sm btn-xs-lg btn-xs-half btn-danger"><i class="bi bi-trash"></i> ' + lang.remove + '</a>' +
  687. '</div>';
  688. }
  689. if (Array.isArray(item.attributes.tags)){
  690. var tags = '';
  691. for (var i = 0; i < item.attributes.tags.length; i++)
  692. tags += '<span class="badge bg-primary tag-badge"><i class="bi bi-tag-fill"></i> ' + escapeHtml(item.attributes.tags[i]) + '</span>';
  693. item.attributes.tags = tags;
  694. } else {
  695. item.attributes.tags = '';
  696. }
  697. });
  698. return json;
  699. }
  700. },
  701. columns: [
  702. {
  703. // placeholder, so checkbox will not block child row toggle
  704. title: '',
  705. data: null,
  706. searchable: false,
  707. orderable: false,
  708. defaultContent: '',
  709. responsivePriority: 1
  710. },
  711. {
  712. title: '',
  713. data: 'chkbox',
  714. searchable: false,
  715. orderable: false,
  716. defaultContent: '',
  717. responsivePriority: 1
  718. },
  719. {
  720. title: "ID",
  721. data: 'id',
  722. responsivePriority: 2,
  723. defaultContent: ''
  724. },
  725. {
  726. title: lang.template,
  727. data: 'template',
  728. responsivePriority: 3,
  729. defaultContent: ''
  730. },
  731. {
  732. title: lang.max_aliases,
  733. data: 'attributes.max_num_aliases_for_domain',
  734. defaultContent: '',
  735. },
  736. {
  737. title: lang.max_mailboxes,
  738. data: 'attributes.max_num_mboxes_for_domain',
  739. defaultContent: '',
  740. },
  741. {
  742. title: lang.mailbox_defquota,
  743. data: 'attributes.def_quota_for_mbox',
  744. defaultContent: '',
  745. },
  746. {
  747. title: lang.max_quota,
  748. data: 'attributes.max_quota_for_mbox',
  749. defaultContent: '',
  750. },
  751. {
  752. title: lang.domain_quota_total,
  753. data: 'attributes.max_quota_for_domain',
  754. defaultContent: '',
  755. },
  756. {
  757. title: lang.gal,
  758. data: 'attributes.gal',
  759. defaultContent: '',
  760. render: function (data, type) {
  761. return 1==data?'<i class="bi bi-check-lg"><span class="sorting-value">1</span></i>':'<i class="bi bi-x-lg"><span class="sorting-value">0</span></i>';
  762. }
  763. },
  764. {
  765. title: lang.backup_mx,
  766. data: 'attributes.backupmx',
  767. defaultContent: '',
  768. render: function (data, type) {
  769. return 1==data?'<i class="bi bi-check-lg"><span class="sorting-value">1</span></i>':'<i class="bi bi-x-lg"><span class="sorting-value">0</span></i>';
  770. }
  771. },
  772. {
  773. title: lang.relay_all,
  774. data: 'attributes.relay_all_recipients',
  775. defaultContent: '',
  776. render: function (data, type) {
  777. return 1==data?'<i class="bi bi-check-lg"><span class="sorting-value">1</span></i>':'<i class="bi bi-x-lg"><span class="sorting-value">0</span></i>';
  778. }
  779. },
  780. {
  781. title: lang.relay_unknown,
  782. data: 'attributes.relay_unknown_only',
  783. defaultContent: '',
  784. render: function (data, type) {
  785. return 1==data?'<i class="bi bi-check-lg"><span class="sorting-value">1</span></i>':'<i class="bi bi-x-lg"><span class="sorting-value">0</span></i>';
  786. }
  787. },
  788. {
  789. title: lang.active,
  790. data: 'attributes.active',
  791. defaultContent: '',
  792. responsivePriority: 4,
  793. render: function (data, type) {
  794. return 1==data?'<i class="bi bi-check-lg"><span class="sorting-value">1</span></i>':'<i class="bi bi-x-lg"><span class="sorting-value">0</span></i>';
  795. }
  796. },
  797. {
  798. title: 'rl_frame',
  799. data: 'attributes.rl_frame',
  800. defaultContent: '',
  801. class: 'none',
  802. },
  803. {
  804. title: 'rl_value',
  805. data: 'attributes.rl_value',
  806. defaultContent: '',
  807. class: 'none',
  808. },
  809. {
  810. title: lang.dkim_domains_selector,
  811. data: 'attributes.dkim_selector',
  812. defaultContent: '',
  813. class: 'none',
  814. },
  815. {
  816. title: lang.dkim_key_length,
  817. data: 'attributes.key_size',
  818. defaultContent: '',
  819. class: 'none',
  820. },
  821. {
  822. title: 'Tags',
  823. data: 'attributes.tags',
  824. defaultContent: '',
  825. className: 'none'
  826. },
  827. {
  828. title: lang.action,
  829. data: 'action',
  830. className: 'dt-sm-head-hidden dt-data-w100 dtr-col-md dt-text-right',
  831. responsivePriority: 6,
  832. defaultContent: ''
  833. },
  834. ]
  835. });
  836. table.on('responsive-resize', function (e, datatable, columns){
  837. hideTableExpandCollapseBtn('#tab-templates-domains', '#templates_domain_table');
  838. });
  839. }
  840. function draw_mailbox_table() {
  841. // just recalc width if instance already exists
  842. if ($.fn.DataTable.isDataTable('#mailbox_table') ) {
  843. $('#mailbox_table').DataTable().columns.adjust().responsive.recalc();
  844. return;
  845. }
  846. var table = $('#mailbox_table').DataTable({
  847. responsive: true,
  848. processing: true,
  849. serverSide: true,
  850. stateSave: true,
  851. pageLength: pagination_size,
  852. dom: "<'row'<'col-sm-12 col-md-6'f><'col-sm-12 col-md-6'l>>" +
  853. "tr" +
  854. "<'row'<'col-sm-12 col-md-5'i><'col-sm-12 col-md-7'p>>",
  855. language: lang_datatables,
  856. initComplete: function(settings, json){
  857. hideTableExpandCollapseBtn('#tab-mailboxes', '#mailbox_table');
  858. },
  859. ajax: {
  860. type: "GET",
  861. url: "/api/v1/get/mailbox/datatables",
  862. dataSrc: function(json){
  863. $.each(json.data, function (i, item) {
  864. item.quota = {
  865. sortBy: item.quota_used,
  866. value: item.quota
  867. }
  868. item.quota.value = (item.quota.value == 0 ? "∞" : humanFileSize(item.quota.value));
  869. item.quota.value = humanFileSize(item.quota_used) + "/" + item.quota.value;
  870. item.max_quota_for_mbox = humanFileSize(item.max_quota_for_mbox);
  871. item.last_mail_login = item.last_imap_login + '/' + item.last_pop3_login + '/' + item.last_smtp_login;
  872. /*
  873. if (!item.rl) {
  874. item.rl = '∞';
  875. } else {
  876. item.rl = $.map(item.rl, function(e){
  877. return e;
  878. }).join('/1');
  879. if (item.rl_scope === 'domain') {
  880. item.rl = '<i class="bi bi-arrow-return-right"></i> ' + item.rl + ' (via ' + item.domain + ')';
  881. }
  882. }
  883. */
  884. item.chkbox = '<input type="checkbox" class="form-check-input" data-id="mailbox" name="multi_select" value="' + encodeURIComponent(item.username) + '" />';
  885. if (item.attributes.passwd_update != '0') {
  886. var last_pw_change = new Date(item.attributes.passwd_update.replace(/-/g, "/"));
  887. item.last_pw_change = last_pw_change.toLocaleDateString(undefined, {year: "numeric", month: "2-digit", day: "2-digit", hour: "2-digit", minute: "2-digit", second: "2-digit"});
  888. } else {
  889. item.last_pw_change = '-';
  890. }
  891. item.tls_enforce_in = '<i class="text-' + (item.attributes.tls_enforce_in == 1 ? 'success bi bi-lock-fill' : 'danger bi bi-unlock-fill') + '"></i>';
  892. item.tls_enforce_out = '<i class="text-' + (item.attributes.tls_enforce_out == 1 ? 'success bi bi-lock-fill' : 'danger bi bi-unlock-fill') + '"></i>';
  893. item.pop3_access = '<i class="text-' + (item.attributes.pop3_access == 1 ? 'success' : 'danger') + ' bi bi-' + (item.attributes.pop3_access == 1 ? 'check-lg' : 'x-lg') + '"></i>';
  894. item.imap_access = '<i class="text-' + (item.attributes.imap_access == 1 ? 'success' : 'danger') + ' bi bi-' + (item.attributes.imap_access == 1 ? 'check-lg' : 'x-lg') + '"></i>';
  895. item.smtp_access = '<i class="text-' + (item.attributes.smtp_access == 1 ? 'success' : 'danger') + ' bi bi-' + (item.attributes.smtp_access == 1 ? 'check-lg' : 'x-lg') + '"></i>';
  896. item.sieve_access = '<i class="text-' + (item.attributes.sieve_access == 1 ? 'success' : 'danger') + ' bi bi-' + (item.attributes.sieve_access == 1 ? 'check-lg' : 'x-lg') + '"></i>';
  897. if (item.attributes.quarantine_notification === 'never') {
  898. item.quarantine_notification = lang.never;
  899. } else if (item.attributes.quarantine_notification === 'hourly') {
  900. item.quarantine_notification = lang.hourly;
  901. } else if (item.attributes.quarantine_notification === 'daily') {
  902. item.quarantine_notification = lang.daily;
  903. } else if (item.attributes.quarantine_notification === 'weekly') {
  904. item.quarantine_notification = lang.weekly;
  905. }
  906. if (item.attributes.quarantine_category === 'reject') {
  907. item.quarantine_category = '<span class="text-danger">' + lang.q_reject + '</span>';
  908. } else if (item.attributes.quarantine_category === 'add_header') {
  909. item.quarantine_category = '<span class="text-warning">' + lang.q_add_header + '</span>';
  910. } else if (item.attributes.quarantine_category === 'all') {
  911. item.quarantine_category = lang.q_all;
  912. }
  913. if (acl_data.login_as === 1) {
  914. item.action = '<div class="btn-group">' +
  915. '<a href="/edit/mailbox/' + encodeURIComponent(item.username) + '" class="btn btn-sm btn-xs-lg btn-xs-half btn-secondary"><i class="bi bi-pencil-fill"></i> ' + lang.edit + '</a>' +
  916. '<a href="#" data-action="delete_selected" data-id="single-mailbox" data-api-url="delete/mailbox" data-item="' + encodeURIComponent(item.username) + '" class="btn btn-sm btn-xs-lg btn-xs-half btn-danger"><i class="bi bi-trash"></i> ' + lang.remove + '</a>' +
  917. '<a href="/index.php?duallogin=' + encodeURIComponent(item.username) + '" class="login_as btn btn-sm btn-xs-lg btn-xs-half btn-success"><i class="bi bi-person-fill"></i> Login</a>';
  918. if (ALLOW_ADMIN_EMAIL_LOGIN) {
  919. item.action += '<a href="/sogo-auth.php?login=' + encodeURIComponent(item.username) + '" class="login_as btn btn-sm btn-xs-lg btn-xs-half btn-primary" target="_blank"><i class="bi bi-envelope-fill"></i> SOGo</a>';
  920. }
  921. item.action += '</div>';
  922. }
  923. else {
  924. item.action = '<div class="btn-group">' +
  925. '<a href="/edit/mailbox/' + encodeURIComponent(item.username) + '" class="btn btn-sm btn-xs-lg btn-xs-half btn-secondary"><i class="bi bi-pencil-fill"></i> ' + lang.edit + '</a>' +
  926. '<a href="#" data-action="delete_selected" data-id="single-mailbox" data-api-url="delete/mailbox" data-item="' + encodeURIComponent(item.username) + '" class="btn btn-sm btn-xs-lg btn-xs-half btn-danger"><i class="bi bi-trash"></i> ' + lang.remove + '</a>' +
  927. '</div>';
  928. }
  929. item.in_use = {
  930. sortBy: item.percent_in_use,
  931. value: '<div class="progress">' +
  932. '<div class="progress-bar-mailbox progress-bar progress-bar-' + item.percent_class + '" role="progressbar" aria-valuenow="' + item.percent_in_use + '" aria-valuemin="0" aria-valuemax="100" ' +
  933. 'style="min-width:2em;width:' + item.percent_in_use + '%">' + item.percent_in_use + '%' + '</div></div>'
  934. };
  935. item.username = escapeHtml(item.username);
  936. if (Array.isArray(item.tags)){
  937. var tags = '';
  938. for (var i = 0; i < item.tags.length; i++)
  939. tags += '<span class="badge bg-primary tag-badge"><i class="bi bi-tag-fill"></i> ' + escapeHtml(item.tags[i]) + '</span>';
  940. item.tags = tags;
  941. } else {
  942. item.tags = '';
  943. }
  944. });
  945. return json.data;
  946. }
  947. },
  948. columns: [
  949. {
  950. // placeholder, so checkbox will not block child row toggle
  951. title: '',
  952. data: null,
  953. searchable: false,
  954. orderable: false,
  955. defaultContent: '',
  956. responsivePriority: 1
  957. },
  958. {
  959. title: '',
  960. data: 'chkbox',
  961. searchable: false,
  962. orderable: false,
  963. defaultContent: '',
  964. responsivePriority: 2
  965. },
  966. {
  967. title: lang.username,
  968. data: 'username',
  969. responsivePriority: 3,
  970. defaultContent: ''
  971. },
  972. {
  973. title: lang.domain_quota,
  974. data: 'quota.value',
  975. searchable: false,
  976. responsivePriority: 8,
  977. defaultContent: ''
  978. },
  979. {
  980. title: lang.last_mail_login,
  981. data: 'last_mail_login',
  982. searchable: false,
  983. defaultContent: '',
  984. responsivePriority: 7,
  985. render: function (data, type) {
  986. res = data.split("/");
  987. return '<div class="badge bg-info mb-2">IMAP @ ' + unix_time_format(Number(res[0])) + '</div><br>' +
  988. '<div class="badge bg-info mb-2">POP3 @ ' + unix_time_format(Number(res[1])) + '</div><br>' +
  989. '<div class="badge bg-info">SMTP @ ' + unix_time_format(Number(res[2])) + '</div>';
  990. }
  991. },
  992. {
  993. title: lang.last_pw_change,
  994. data: 'last_pw_change',
  995. searchable: false,
  996. defaultContent: ''
  997. },
  998. {
  999. title: lang.in_use,
  1000. data: 'in_use.value',
  1001. searchable: false,
  1002. defaultContent: '',
  1003. responsivePriority: 9,
  1004. className: 'dt-data-w100'
  1005. },
  1006. {
  1007. title: lang.fname,
  1008. data: 'name',
  1009. defaultContent: '',
  1010. className: 'none'
  1011. },
  1012. {
  1013. title: lang.domain,
  1014. data: 'domain',
  1015. defaultContent: '',
  1016. className: 'none',
  1017. },
  1018. {
  1019. title: lang.iam,
  1020. data: 'authsource',
  1021. defaultContent: '',
  1022. className: 'none',
  1023. render: function (data, type) {
  1024. return '<span class="badge bg-primary">' + data + '<i class="ms-2 bi bi-person-circle"></i></i></span>';
  1025. }
  1026. },
  1027. {
  1028. title: lang.tls_enforce_in,
  1029. data: 'tls_enforce_in',
  1030. defaultContent: '',
  1031. className: 'none'
  1032. },
  1033. {
  1034. title: lang.tls_enforce_out,
  1035. data: 'tls_enforce_out',
  1036. defaultContent: '',
  1037. className: 'none'
  1038. },
  1039. {
  1040. title: 'SMTP',
  1041. data: 'smtp_access',
  1042. defaultContent: '',
  1043. className: 'none'
  1044. },
  1045. {
  1046. title: 'IMAP',
  1047. data: 'imap_access',
  1048. defaultContent: '',
  1049. className: 'none'
  1050. },
  1051. {
  1052. title: 'POP3',
  1053. data: 'pop3_access',
  1054. defaultContent: '',
  1055. className: 'none'
  1056. },
  1057. {
  1058. title: 'SIEVE',
  1059. data: 'sieve_access',
  1060. defaultContent: '',
  1061. className: 'none'
  1062. },
  1063. {
  1064. title: lang.quarantine_notification,
  1065. data: 'quarantine_notification',
  1066. defaultContent: '',
  1067. className: 'none'
  1068. },
  1069. {
  1070. title: lang.quarantine_category,
  1071. data: 'quarantine_category',
  1072. defaultContent: '',
  1073. className: 'none'
  1074. },
  1075. {
  1076. title: lang.msg_num,
  1077. data: 'messages',
  1078. searchable: false,
  1079. defaultContent: '',
  1080. responsivePriority: 5
  1081. },
  1082. {
  1083. title: lang.created_on,
  1084. data: 'created',
  1085. defaultContent: '',
  1086. className: 'none'
  1087. },
  1088. {
  1089. title: lang.last_modified,
  1090. data: 'modified',
  1091. defaultContent: '',
  1092. className: 'none'
  1093. },
  1094. {
  1095. title: 'Tags',
  1096. data: 'tags',
  1097. searchable: true,
  1098. defaultContent: '',
  1099. className: 'none'
  1100. },
  1101. {
  1102. title: lang.active,
  1103. data: 'active',
  1104. searchable: false,
  1105. defaultContent: '',
  1106. responsivePriority: 4,
  1107. render: function (data, type) {
  1108. return 1==data?'<i class="bi bi-check-lg"><span class="sorting-value">1</span></i>':(0==data?'<i class="bi bi-x-lg"><span class="sorting-value">0</span></i>':2==data&&'&#8212;');
  1109. }
  1110. },
  1111. {
  1112. title: lang.action,
  1113. data: 'action',
  1114. searchable: false,
  1115. orderable: false,
  1116. className: 'dt-sm-head-hidden dt-data-w100 dtr-col-md dt-text-right',
  1117. responsivePriority: 6,
  1118. defaultContent: ''
  1119. }
  1120. ]
  1121. });
  1122. table.on('responsive-resize', function (e, datatable, columns){
  1123. hideTableExpandCollapseBtn('#tab-mailboxes', '#mailbox_table');
  1124. });
  1125. }
  1126. function draw_templates_mbox_table() {
  1127. // just recalc width if instance already exists
  1128. if ($.fn.DataTable.isDataTable('#templates_mbox_table') ) {
  1129. $('#templates_mbox_table').DataTable().columns.adjust().responsive.recalc();
  1130. return;
  1131. }
  1132. var table = $('#templates_mbox_table').DataTable({
  1133. responsive: true,
  1134. processing: true,
  1135. serverSide: false,
  1136. stateSave: true,
  1137. pageLength: pagination_size,
  1138. dom: "<'row'<'col-sm-12 col-md-6'f><'col-sm-12 col-md-6'l>>" +
  1139. "tr" +
  1140. "<'row'<'col-sm-12 col-md-5'i><'col-sm-12 col-md-7'p>>",
  1141. language: lang_datatables,
  1142. order: [[2, 'desc']],
  1143. initComplete: function(){
  1144. hideTableExpandCollapseBtn('#tab-templates-mbox', '#templates_mbox_table');
  1145. },
  1146. ajax: {
  1147. type: "GET",
  1148. url: "/api/v1/get/mailbox/template/all",
  1149. dataSrc: function(json){
  1150. $.each(json, function (i, item) {
  1151. item.chkbox = '<input type="checkbox" class="form-check-input" data-id="mailbox_template" name="multi_select" value="' + encodeURIComponent(item.id) + '" />';
  1152. item.template = escapeHtml(item.template);
  1153. if (item.attributes.rl_frame === "s"){
  1154. item.attributes.rl_frame = lang_rl.second;
  1155. } else if (item.attributes.rl_frame === "m"){
  1156. item.attributes.rl_frame = lang_rl.minute;
  1157. } else if (item.attributes.rl_frame === "h"){
  1158. item.attributes.rl_frame = lang_rl.hour;
  1159. } else if (item.attributes.rl_frame === "d"){
  1160. item.attributes.rl_frame = lang_rl.day;
  1161. }
  1162. item.attributes.rl_value = escapeHtml(item.attributes.rl_value);
  1163. item.attributes.quota = humanFileSize(item.attributes.quota);
  1164. item.attributes.tls_enforce_in = '<i class="text-' + (item.attributes.tls_enforce_in == 1 ? 'success bi bi-lock-fill' : 'danger bi bi-unlock-fill') + '"><span class="sorting-value">' + (item.attributes.tls_enforce_in == 1 ? '1' : '0') + '</span></i>';
  1165. item.attributes.tls_enforce_out = '<i class="text-' + (item.attributes.tls_enforce_out == 1 ? 'success bi bi-lock-fill' : 'danger bi bi-unlock-fill') + '"><span class="sorting-value">' + (item.attributes.tls_enforce_out == 1 ? '1' : '0') + '</span></i>';
  1166. item.attributes.pop3_access = '<i class="text-' + (item.attributes.pop3_access == 1 ? 'success' : 'danger') + ' bi bi-' + (item.attributes.pop3_access == 1 ? 'check-lg' : 'x-lg') + '"><span class="sorting-value">' + (item.attributes.pop3_access == 1 ? '1' : '0') + '</span></i>';
  1167. item.attributes.imap_access = '<i class="text-' + (item.attributes.imap_access == 1 ? 'success' : 'danger') + ' bi bi-' + (item.attributes.imap_access == 1 ? 'check-lg' : 'x-lg') + '"><span class="sorting-value">' + (item.attributes.imap_access == 1 ? '1' : '0') + '</span></i>';
  1168. item.attributes.smtp_access = '<i class="text-' + (item.attributes.smtp_access == 1 ? 'success' : 'danger') + ' bi bi-' + (item.attributes.smtp_access == 1 ? 'check-lg' : 'x-lg') + '"><span class="sorting-value">' + (item.attributes.smtp_access == 1 ? '1' : '0') + '</span></i>';
  1169. item.attributes.sieve_access = '<i class="text-' + (item.attributes.sieve_access == 1 ? 'success' : 'danger') + ' bi bi-' + (item.attributes.sieve_access == 1 ? 'check-lg' : 'x-lg') + '"><span class="sorting-value">' + (item.attributes.sieve_access == 1 ? '1' : '0') + '</span></i>';
  1170. item.attributes.sogo_access = '<i class="text-' + (item.attributes.sogo_access == 1 ? 'success' : 'danger') + ' bi bi-' + (item.attributes.sogo_access == 1 ? 'check-lg' : 'x-lg') + '"><span class="sorting-value">' + (item.attributes.sogo_access == 1 ? '1' : '0') + '</span></i>';
  1171. if (item.attributes.quarantine_notification === 'never') {
  1172. item.attributes.quarantine_notification = lang.never;
  1173. } else if (item.attributes.quarantine_notification === 'hourly') {
  1174. item.attributes.quarantine_notification = lang.hourly;
  1175. } else if (item.attributes.quarantine_notification === 'daily') {
  1176. item.attributes.quarantine_notification = lang.daily;
  1177. } else if (item.attributes.quarantine_notification === 'weekly') {
  1178. item.attributes.quarantine_notification = lang.weekly;
  1179. }
  1180. if (item.attributes.quarantine_category === 'reject') {
  1181. item.attributes.quarantine_category = '<span class="text-danger">' + lang.q_reject + '</span>';
  1182. } else if (item.attributes.quarantine_category === 'add_header') {
  1183. item.attributes.quarantine_category = '<span class="text-warning">' + lang.q_add_header + '</span>';
  1184. } else if (item.attributes.quarantine_category === 'all') {
  1185. item.attributes.quarantine_category = lang.q_all;
  1186. }
  1187. if (item.template.toLowerCase() == "default"){
  1188. item.action = '<div class="btn-group">' +
  1189. '<a href="/edit/template/' + encodeURIComponent(item.id) + '" class="btn btn-sm btn-xs-lg btn-xs-half btn-secondary"><i class="bi bi-pencil-fill"></i> ' + lang.edit + '</a>' +
  1190. '</div>';
  1191. }
  1192. else {
  1193. item.action = '<div class="btn-group">' +
  1194. '<a href="/edit/template/' + encodeURIComponent(item.id) + '" class="btn btn-sm btn-xs-lg btn-xs-half btn-secondary"><i class="bi bi-pencil-fill"></i> ' + lang.edit + '</a>' +
  1195. '<a href="#" data-action="delete_selected" data-id="single-template" data-api-url="delete/mailbox/template" data-item="' + encodeURIComponent(item.id) + '" class="btn btn-sm btn-xs-lg btn-xs-half btn-danger"><i class="bi bi-trash"></i> ' + lang.remove + '</a>' +
  1196. '</div>';
  1197. }
  1198. if (Array.isArray(item.attributes.tags)){
  1199. var tags = '';
  1200. for (var i = 0; i < item.attributes.tags.length; i++)
  1201. tags += '<span class="badge bg-primary tag-badge"><i class="bi bi-tag-fill"></i> ' + escapeHtml(item.attributes.tags[i]) + '</span>';
  1202. item.attributes.tags = tags;
  1203. } else {
  1204. item.attributes.tags = '';
  1205. }
  1206. });
  1207. return json;
  1208. }
  1209. },
  1210. columns: [
  1211. {
  1212. // placeholder, so checkbox will not block child row toggle
  1213. title: '',
  1214. data: null,
  1215. searchable: false,
  1216. orderable: false,
  1217. defaultContent: '',
  1218. responsivePriority: 1
  1219. },
  1220. {
  1221. title: '',
  1222. data: 'chkbox',
  1223. searchable: false,
  1224. orderable: false,
  1225. defaultContent: '',
  1226. responsivePriority: 1
  1227. },
  1228. {
  1229. title: "ID",
  1230. data: 'id',
  1231. responsivePriority: 2,
  1232. defaultContent: ''
  1233. },
  1234. {
  1235. title: lang.template,
  1236. data: 'template',
  1237. responsivePriority: 3,
  1238. defaultContent: ''
  1239. },
  1240. {
  1241. title: lang.domain_quota,
  1242. data: 'attributes.quota',
  1243. defaultContent: '',
  1244. },
  1245. {
  1246. title: lang.iam,
  1247. data: 'attributes.authsource',
  1248. defaultContent: '',
  1249. render: function (data, type) {
  1250. data = data ? '<span class="badge bg-primary">' + data + '<i class="ms-2 bi bi-person-circle"></i></i></span>' : '<i class="bi bi-x-lg"></i>';
  1251. return data;
  1252. }
  1253. },
  1254. {
  1255. title: lang.tls_enforce_in,
  1256. data: 'attributes.tls_enforce_in',
  1257. defaultContent: ''
  1258. },
  1259. {
  1260. title: lang.tls_enforce_out,
  1261. data: 'attributes.tls_enforce_out',
  1262. defaultContent: ''
  1263. },
  1264. {
  1265. title: 'SMTP',
  1266. data: 'attributes.smtp_access',
  1267. defaultContent: '',
  1268. },
  1269. {
  1270. title: 'IMAP',
  1271. data: 'attributes.imap_access',
  1272. defaultContent: '',
  1273. },
  1274. {
  1275. title: 'POP3',
  1276. data: 'attributes.pop3_access',
  1277. defaultContent: '',
  1278. },
  1279. {
  1280. title: 'SIEVE',
  1281. data: 'attributes.sieve_access',
  1282. defaultContent: '',
  1283. },
  1284. {
  1285. title: 'SOGO',
  1286. data: 'attributes.sogo_access',
  1287. defaultContent: '',
  1288. },
  1289. {
  1290. title: lang.quarantine_notification,
  1291. data: 'attributes.quarantine_notification',
  1292. defaultContent: '',
  1293. className: 'none'
  1294. },
  1295. {
  1296. title: lang.quarantine_category,
  1297. data: 'attributes.quarantine_category',
  1298. defaultContent: '',
  1299. className: 'none'
  1300. },
  1301. {
  1302. title: lang.force_pw_update,
  1303. data: 'attributes.force_pw_update',
  1304. defaultContent: '',
  1305. class: 'none',
  1306. render: function (data, type) {
  1307. return 1==data?'<i class="bi bi-check-lg"></i>':'<i class="bi bi-x-lg"></i>';
  1308. }
  1309. },
  1310. {
  1311. title: "rl_frame",
  1312. data: 'attributes.rl_frame',
  1313. defaultContent: '',
  1314. class: 'none',
  1315. },
  1316. {
  1317. title: 'rl_value',
  1318. data: 'attributes.rl_value',
  1319. defaultContent: '',
  1320. class: 'none',
  1321. },
  1322. {
  1323. title: 'Tags',
  1324. data: 'attributes.tags',
  1325. defaultContent: '',
  1326. className: 'none'
  1327. },
  1328. {
  1329. title: lang.active,
  1330. data: 'attributes.active',
  1331. defaultContent: '',
  1332. responsivePriority: 4,
  1333. render: function (data, type) {
  1334. return 1==data?'<i class="bi bi-check-lg"><span class="sorting-value">1</span></i>':(0==data?'<i class="bi bi-x-lg"><span class="sorting-value">0</span></i>':2==data&&'&#8212;');
  1335. }
  1336. },
  1337. {
  1338. title: lang.action,
  1339. data: 'action',
  1340. className: 'dt-sm-head-hidden dt-data-w100 dtr-col-md dt-text-right',
  1341. responsivePriority: 6,
  1342. defaultContent: ''
  1343. },
  1344. ]
  1345. });
  1346. table.on('responsive-resize', function (e, datatable, columns){
  1347. hideTableExpandCollapseBtn('#tab-templates-mbox', '#templates_mbox_table');
  1348. });
  1349. }
  1350. function draw_resource_table() {
  1351. // just recalc width if instance already exists
  1352. if ($.fn.DataTable.isDataTable('#resource_table') ) {
  1353. $('#resource_table').DataTable().columns.adjust().responsive.recalc();
  1354. return;
  1355. }
  1356. var table = $('#resource_table').DataTable({
  1357. responsive: true,
  1358. processing: true,
  1359. serverSide: false,
  1360. stateSave: true,
  1361. pageLength: pagination_size,
  1362. dom: "<'row'<'col-sm-12 col-md-6'f><'col-sm-12 col-md-6'l>>" +
  1363. "tr" +
  1364. "<'row'<'col-sm-12 col-md-5'i><'col-sm-12 col-md-7'p>>",
  1365. language: lang_datatables,
  1366. initComplete: function(settings, json){
  1367. hideTableExpandCollapseBtn('#tab-resources', '#resource_table');
  1368. filterByDomain(json, 5, table);
  1369. },
  1370. ajax: {
  1371. type: "GET",
  1372. url: "/api/v1/get/resource/all",
  1373. dataSrc: function(json){
  1374. $.each(json, function (i, item) {
  1375. if (item.multiple_bookings == '0') {
  1376. item.multiple_bookings = '<span id="active-script" class="badge fs-6 bg-success">' + lang.booking_0_short + '</span>';
  1377. } else if (item.multiple_bookings == '-1') {
  1378. item.multiple_bookings = '<span id="active-script" class="badge fs-6 bg-warning">' + lang.booking_lt0_short + '</span>';
  1379. } else {
  1380. item.multiple_bookings = '<span id="active-script" class="badge fs-6 bg-danger">' + lang.booking_custom_short + ' (' + item.multiple_bookings + ')</span>';
  1381. }
  1382. item.action = '<div class="btn-group">' +
  1383. '<a href="/edit/resource/' + encodeURIComponent(item.name) + '" class="btn btn-sm btn-xs-lg btn-xs-half btn-secondary"><i class="bi bi-pencil-fill"></i> ' + lang.edit + '</a>' +
  1384. '<a href="#" data-action="delete_selected" data-id="single-resource" data-api-url="delete/resource" data-item="' + item.name + '" class="btn btn-sm btn-xs-lg btn-xs-half btn-danger"><i class="bi bi-trash"></i> ' + lang.remove + '</a>' +
  1385. '</div>';
  1386. item.chkbox = '<input type="checkbox" class="form-check-input" data-id="resource" name="multi_select" value="' + encodeURIComponent(item.name) + '" />';
  1387. item.name = escapeHtml(item.name);
  1388. item.description = escapeHtml(item.description);
  1389. });
  1390. return json;
  1391. }
  1392. },
  1393. columns: [
  1394. {
  1395. // placeholder, so checkbox will not block child row toggle
  1396. title: '',
  1397. data: null,
  1398. searchable: false,
  1399. orderable: false,
  1400. defaultContent: '',
  1401. responsivePriority: 1
  1402. },
  1403. {
  1404. title: '',
  1405. data: 'chkbox',
  1406. searchable: false,
  1407. orderable: false,
  1408. defaultContent: '',
  1409. responsivePriority: 2
  1410. },
  1411. {
  1412. title: lang.description,
  1413. data: 'description',
  1414. responsivePriority: 3,
  1415. defaultContent: ''
  1416. },
  1417. {
  1418. title: lang.alias,
  1419. data: 'name',
  1420. defaultContent: ''
  1421. },
  1422. {
  1423. title: lang.kind,
  1424. data: 'kind',
  1425. defaultContent: ''
  1426. },
  1427. {
  1428. title: lang.domain,
  1429. data: 'domain',
  1430. responsivePriority: 4,
  1431. defaultContent: ''
  1432. },
  1433. {
  1434. title: lang.multiple_bookings,
  1435. data: 'multiple_bookings',
  1436. defaultContent: ''
  1437. },
  1438. {
  1439. title: lang.active,
  1440. data: 'active',
  1441. defaultContent: '',
  1442. render: function (data, type) {
  1443. return 1==data?'<i class="bi bi-check-lg"><span class="sorting-value">1</span></i>':(0==data?'<i class="bi bi-x-lg"><span class="sorting-value">0</span></i>':2==data&&'&#8212;');
  1444. }
  1445. },
  1446. {
  1447. title: lang.action,
  1448. data: 'action',
  1449. responsivePriority: 5,
  1450. defaultContent: '',
  1451. className: 'dt-sm-head-hidden dt-data-w100 dtr-col-md dt-text-right'
  1452. },
  1453. ]
  1454. });
  1455. table.on('responsive-resize', function (e, datatable, columns){
  1456. hideTableExpandCollapseBtn('#tab-resources', '#resource_table');
  1457. });
  1458. }
  1459. function draw_bcc_table() {
  1460. $.get("/api/v1/get/bcc-destination-options", function(data){
  1461. var optgroup = "";
  1462. // Domains
  1463. if (data.domains && data.domains.length > 0) {
  1464. optgroup = "<optgroup label='" + lang.domains + "'>";
  1465. $.each(data.domains, function(index, domain){
  1466. optgroup += "<option value='" + domain + "'>" + domain + "</option>";
  1467. });
  1468. optgroup += "</optgroup>";
  1469. $('#bcc-local-dest').append(optgroup);
  1470. }
  1471. // Alias domains
  1472. if (data.alias_domains && data.alias_domains.length > 0) {
  1473. optgroup = "<optgroup label='" + lang.domain_aliases + "'>";
  1474. $.each(data.alias_domains, function(index, alias_domain){
  1475. optgroup += "<option value='" + alias_domain + "'>" + alias_domain + "</option>";
  1476. });
  1477. optgroup += "</optgroup>"
  1478. $('#bcc-local-dest').append(optgroup);
  1479. }
  1480. // Mailboxes and aliases
  1481. if (data.mailboxes && Object.keys(data.mailboxes).length > 0) {
  1482. $.each(data.mailboxes, function(mailbox, aliases){
  1483. optgroup = "<optgroup label='" + mailbox + "'>";
  1484. $.each(aliases, function(index, alias){
  1485. optgroup += "<option value='" + alias + "'>" + alias + "</option>";
  1486. });
  1487. optgroup += "</optgroup>";
  1488. $('#bcc-local-dest').append(optgroup);
  1489. });
  1490. }
  1491. // Recreate picker
  1492. $('#bcc-local-dest').selectpicker('refresh');
  1493. });
  1494. // just recalc width if instance already exists
  1495. if ($.fn.DataTable.isDataTable('#bcc_table') ) {
  1496. $('#bcc_table').DataTable().columns.adjust().responsive.recalc();
  1497. return;
  1498. }
  1499. var table = $('#bcc_table').DataTable({
  1500. responsive: true,
  1501. processing: true,
  1502. serverSide: false,
  1503. stateSave: true,
  1504. pageLength: pagination_size,
  1505. dom: "<'row'<'col-sm-12 col-md-6'f><'col-sm-12 col-md-6'l>>" +
  1506. "tr" +
  1507. "<'row'<'col-sm-12 col-md-5'i><'col-sm-12 col-md-7'p>>",
  1508. language: lang_datatables,
  1509. order: [[2, 'desc']],
  1510. initComplete: function(settings, json){
  1511. hideTableExpandCollapseBtn('#collapse-tab-bcc', '#bcc_table');
  1512. filterByDomain(json, 6, table);
  1513. },
  1514. ajax: {
  1515. type: "GET",
  1516. url: "/api/v1/get/bcc/all",
  1517. dataSrc: function(json){
  1518. $.each(json, function (i, item) {
  1519. item.action = '<div class="btn-group">' +
  1520. '<a href="/edit/bcc/' + item.id + '" class="btn btn-sm btn-xs-lg btn-xs-half btn-secondary"><i class="bi bi-pencil-fill"></i> ' + lang.edit + '</a>' +
  1521. '<a href="#" data-action="delete_selected" data-id="single-bcc" data-api-url="delete/bcc" data-item="' + item.id + '" class="btn btn-sm btn-xs-lg btn-xs-half btn-danger"><i class="bi bi-trash"></i> ' + lang.remove + '</a>' +
  1522. '</div>';
  1523. item.chkbox = '<input type="checkbox" class="form-check-input" data-id="bcc" name="multi_select" value="' + item.id + '" />';
  1524. item.local_dest = escapeHtml(item.local_dest);
  1525. item.bcc_dest = escapeHtml(item.bcc_dest);
  1526. if (item.type == 'sender') {
  1527. item.type = '<span id="active-script" class="badge fs-6 bg-success">' + lang.bcc_sender_map + '</span>';
  1528. } else {
  1529. item.type = '<span id="inactive-script" class="badge fs-6 bg-warning">' + lang.bcc_rcpt_map + '</span>';
  1530. }
  1531. });
  1532. return json;
  1533. }
  1534. },
  1535. columns: [
  1536. {
  1537. // placeholder, so checkbox will not block child row toggle
  1538. title: '',
  1539. data: null,
  1540. searchable: false,
  1541. orderable: false,
  1542. defaultContent: '',
  1543. responsivePriority: 1
  1544. },
  1545. {
  1546. title: '',
  1547. data: 'chkbox',
  1548. searchable: false,
  1549. orderable: false,
  1550. defaultContent: '',
  1551. responsivePriority: 2
  1552. },
  1553. {
  1554. title: 'ID',
  1555. data: 'id',
  1556. responsivePriority: 3,
  1557. defaultContent: ''
  1558. },
  1559. {
  1560. title: lang.bcc_type,
  1561. data: 'type',
  1562. defaultContent: ''
  1563. },
  1564. {
  1565. title: lang.bcc_local_dest,
  1566. data: 'local_dest',
  1567. defaultContent: ''
  1568. },
  1569. {
  1570. title: lang.bcc_destinations,
  1571. data: 'bcc_dest',
  1572. defaultContent: ''
  1573. },
  1574. {
  1575. title: lang.domain,
  1576. data: 'domain',
  1577. responsivePriority: 4,
  1578. defaultContent: ''
  1579. },
  1580. {
  1581. title: lang.active,
  1582. data: 'active',
  1583. defaultContent: '',
  1584. render: function (data, type) {
  1585. return 1==data?'<i class="bi bi-check-lg"><span class="sorting-value">1</span></i>':(0==data?'<i class="bi bi-x-lg"><span class="sorting-value">0</span></i>':2==data&&'&#8212;');
  1586. }
  1587. },
  1588. {
  1589. title: lang.action,
  1590. data: 'action',
  1591. className: 'dt-sm-head-hidden dt-data-w100 dtr-col-md dt-text-right',
  1592. responsivePriority: 5,
  1593. defaultContent: ''
  1594. },
  1595. ]
  1596. });
  1597. table.on('responsive-resize', function (e, datatable, columns){
  1598. hideTableExpandCollapseBtn('#collapse-tab-bcc', '#bcc_table');
  1599. });
  1600. }
  1601. function draw_recipient_map_table() {
  1602. // just recalc width if instance already exists
  1603. if ($.fn.DataTable.isDataTable('#recipient_map_table') ) {
  1604. $('#recipient_map_table').DataTable().columns.adjust().responsive.recalc();
  1605. return;
  1606. }
  1607. var table = $('#recipient_map_table').DataTable({
  1608. responsive: true,
  1609. processing: true,
  1610. serverSide: false,
  1611. stateSave: true,
  1612. pageLength: pagination_size,
  1613. dom: "<'row'<'col-sm-12 col-md-6'f><'col-sm-12 col-md-6'l>>" +
  1614. "tr" +
  1615. "<'row'<'col-sm-12 col-md-5'i><'col-sm-12 col-md-7'p>>",
  1616. language: lang_datatables,
  1617. order: [[2, 'desc']],
  1618. initComplete: function(){
  1619. hideTableExpandCollapseBtn('#collapse-tab-bcc-filters', '#recipient_map_table');
  1620. },
  1621. ajax: {
  1622. type: "GET",
  1623. url: "/api/v1/get/recipient_map/all",
  1624. dataSrc: function(json){
  1625. if (role !== "admin") return null;
  1626. $.each(json, function (i, item) {
  1627. item.recipient_map_old = escapeHtml(item.recipient_map_old);
  1628. item.recipient_map_new = escapeHtml(item.recipient_map_new);
  1629. item.action = '<div class="btn-group">' +
  1630. '<a href="/edit/recipient_map/' + item.id + '" class="btn btn-sm btn-xs-lg btn-xs-half btn-secondary"><i class="bi bi-pencil-fill"></i> ' + lang.edit + '</a>' +
  1631. '<a href="#" data-action="delete_selected" data-id="single-recipient_map" data-api-url="delete/recipient_map" data-item="' + item.id + '" class="btn btn-sm btn-xs-lg btn-xs-half btn-danger"><i class="bi bi-trash"></i> ' + lang.remove + '</a>' +
  1632. '</div>';
  1633. item.chkbox = '<input type="checkbox" class="form-check-input" data-id="recipient_map" name="multi_select" value="' + item.id + '" />';
  1634. });
  1635. return json;
  1636. }
  1637. },
  1638. columns: [
  1639. {
  1640. // placeholder, so checkbox will not block child row toggle
  1641. title: '',
  1642. data: null,
  1643. searchable: false,
  1644. orderable: false,
  1645. defaultContent: '',
  1646. responsivePriority: 1
  1647. },
  1648. {
  1649. title: '',
  1650. data: 'chkbox',
  1651. searchable: false,
  1652. orderable: false,
  1653. defaultContent: '',
  1654. responsivePriority: 2
  1655. },
  1656. {
  1657. title: 'ID',
  1658. data: 'id',
  1659. responsivePriority: 3,
  1660. defaultContent: ''
  1661. },
  1662. {
  1663. title: lang.recipient_map_old,
  1664. data: 'recipient_map_old',
  1665. defaultContent: ''
  1666. },
  1667. {
  1668. title: lang.recipient_map_new,
  1669. data: 'recipient_map_new',
  1670. defaultContent: '',
  1671. responsivePriority: 4
  1672. },
  1673. {
  1674. title: lang.active,
  1675. data: 'active',
  1676. defaultContent: '',
  1677. render: function (data, type) {
  1678. return 1==data?'<i class="bi bi-check-lg"><span class="sorting-value">1</span></i>':0==data&&'<i class="bi bi-x-lg"><span class="sorting-value">0</span></i>';
  1679. }
  1680. },
  1681. {
  1682. title: lang.action,
  1683. data: 'action',
  1684. className: 'dt-sm-head-hidden dt-data-w100 dtr-col-md dt-text-right',
  1685. responsivePriority: 5,
  1686. defaultContent: ''
  1687. },
  1688. ]
  1689. });
  1690. table.on('responsive-resize', function (e, datatable, columns){
  1691. hideTableExpandCollapseBtn('#collapse-tab-bcc-filters', '#recipient_map_table');
  1692. });
  1693. }
  1694. function draw_tls_policy_table() {
  1695. // just recalc width if instance already exists
  1696. if ($.fn.DataTable.isDataTable('#tls_policy_table') ) {
  1697. $('#tls_policy_table').DataTable().columns.adjust().responsive.recalc();
  1698. return;
  1699. }
  1700. var table = $('#tls_policy_table').DataTable({
  1701. responsive: true,
  1702. processing: true,
  1703. serverSide: false,
  1704. stateSave: true,
  1705. pageLength: pagination_size,
  1706. dom: "<'row'<'col-sm-12 col-md-6'f><'col-sm-12 col-md-6'l>>" +
  1707. "tr" +
  1708. "<'row'<'col-sm-12 col-md-5'i><'col-sm-12 col-md-7'p>>",
  1709. language: lang_datatables,
  1710. order: [[2, 'desc']],
  1711. initComplete: function(){
  1712. hideTableExpandCollapseBtn('#tab-tls-policy', '#tls_policy_table');
  1713. },
  1714. ajax: {
  1715. type: "GET",
  1716. url: "/api/v1/get/tls-policy-map/all",
  1717. dataSrc: function(json){
  1718. if (role !== "admin") return null;
  1719. $.each(json, function (i, item) {
  1720. item.dest = escapeHtml(item.dest);
  1721. item.policy = '<b>' + escapeHtml(item.policy) + '</b>';
  1722. if (item.parameters == '') {
  1723. item.parameters = '<code>-</code>';
  1724. } else {
  1725. item.parameters = '<code>' + escapeHtml(item.parameters) + '</code>';
  1726. }
  1727. item.action = '<div class="btn-group">' +
  1728. '<a href="/edit/tls_policy_map/' + item.id + '" class="btn btn-sm btn-xs-lg btn-xs-half btn-secondary"><i class="bi bi-pencil-fill"></i> ' + lang.edit + '</a>' +
  1729. '<a href="#" data-action="delete_selected" data-id="single-tls-policy-map" data-api-url="delete/tls-policy-map" data-item="' + item.id + '" class="btn btn-sm btn-xs-lg btn-xs-half btn-danger"><i class="bi bi-trash"></i> ' + lang.remove + '</a>' +
  1730. '</div>';
  1731. item.chkbox = '<input type="checkbox" class="form-check-input" data-id="tls-policy-map" name="multi_select" value="' + item.id + '" />';
  1732. });
  1733. return json;
  1734. }
  1735. },
  1736. columns: [
  1737. {
  1738. // placeholder, so checkbox will not block child row toggle
  1739. title: '',
  1740. data: null,
  1741. searchable: false,
  1742. orderable: false,
  1743. defaultContent: '',
  1744. responsivePriority: 1
  1745. },
  1746. {
  1747. title: '',
  1748. data: 'chkbox',
  1749. searchable: false,
  1750. orderable: false,
  1751. defaultContent: '',
  1752. responsivePriority: 2
  1753. },
  1754. {
  1755. title: 'ID',
  1756. data: 'id',
  1757. responsivePriority: 3,
  1758. defaultContent: ''
  1759. },
  1760. {
  1761. title: lang.tls_map_dest,
  1762. data: 'dest',
  1763. defaultContent: '',
  1764. responsivePriority: 4
  1765. },
  1766. {
  1767. title: lang.tls_map_policy,
  1768. data: 'policy',
  1769. defaultContent: ''
  1770. },
  1771. {
  1772. title: lang.tls_map_parameters,
  1773. data: 'parameters',
  1774. defaultContent: ''
  1775. },
  1776. {
  1777. title: lang.active,
  1778. data: 'active',
  1779. defaultContent: '',
  1780. render: function (data, type) {
  1781. return 1==data?'<i class="bi bi-check-lg"><span class="sorting-value">1</span></i>':0==data&&'<i class="bi bi-x-lg"><span class="sorting-value">0</span></i>';
  1782. }
  1783. },
  1784. {
  1785. title: lang.action,
  1786. data: 'action',
  1787. className: 'dt-sm-head-hidden dt-data-w100 dtr-col-md dt-text-right',
  1788. responsivePriority: 5,
  1789. defaultContent: ''
  1790. },
  1791. ]
  1792. });
  1793. table.on('responsive-resize', function (e, datatable, columns){
  1794. hideTableExpandCollapseBtn('#tab-tls-policy', '#tls_policy_table');
  1795. });
  1796. }
  1797. function draw_alias_table() {
  1798. // just recalc width if instance already exists
  1799. if ($.fn.DataTable.isDataTable('#alias_table') ) {
  1800. $('#alias_table').DataTable().columns.adjust().responsive.recalc();
  1801. return;
  1802. }
  1803. var table = $('#alias_table').DataTable({
  1804. responsive: true,
  1805. processing: true,
  1806. serverSide: false,
  1807. stateSave: true,
  1808. pageLength: pagination_size,
  1809. dom: "<'row'<'col-sm-12 col-md-6'f><'col-sm-12 col-md-6'l>>" +
  1810. "tr" +
  1811. "<'row'<'col-sm-12 col-md-5'i><'col-sm-12 col-md-7'p>>",
  1812. language: lang_datatables,
  1813. order: [[2, 'desc']],
  1814. initComplete: function(settings, json){
  1815. hideTableExpandCollapseBtn('#tab-mbox-aliases', '#alias_table');
  1816. filterByDomain(json, 5, table);
  1817. },
  1818. ajax: {
  1819. type: "GET",
  1820. url: "/api/v1/get/alias/all",
  1821. dataSrc: function(json){
  1822. $.each(json, function (i, item) {
  1823. item.action = '<div class="btn-group">' +
  1824. '<a href="/edit/alias/' + encodeURIComponent(item.id) + '" class="btn btn-sm btn-xs-lg btn-xs-half btn-secondary"><i class="bi bi-pencil-fill"></i> ' + lang.edit + '</a>' +
  1825. '<a href="#" data-action="delete_selected" data-id="single-alias" data-api-url="delete/alias" data-item="' + encodeURIComponent(item.id) + '" class="btn btn-sm btn-xs-lg btn-xs-half btn-danger"><i class="bi bi-trash"></i> ' + lang.remove + '</a>' +
  1826. '</div>';
  1827. item.chkbox = '<input type="checkbox" class="form-check-input" data-id="alias" name="multi_select" value="' + encodeURIComponent(item.id) + '" />';
  1828. item.goto = escapeHtml(item.goto.replace(/,/g, " "));
  1829. if (item.public_comment !== null) {
  1830. item.public_comment = escapeHtml(item.public_comment);
  1831. }
  1832. else {
  1833. item.public_comment = '-';
  1834. }
  1835. if (item.private_comment !== null) {
  1836. item.private_comment = escapeHtml(item.private_comment);
  1837. }
  1838. else {
  1839. item.private_comment = '-';
  1840. }
  1841. if (item.is_catch_all == 1) {
  1842. item.address = '<div class="badge fs-6 bg-secondary">' + lang.catch_all + '</div> ' + escapeHtml(item.address);
  1843. }
  1844. else {
  1845. item.address = escapeHtml(item.address);
  1846. }
  1847. if (item.goto == "null@localhost") {
  1848. item.goto = '⤷ <i class="bi bi-trash" style="font-size:12px"></i>';
  1849. }
  1850. else if (item.goto == "spam@localhost") {
  1851. item.goto = '<span class="badge fs-6 bg-danger">' + lang.goto_spam + '</span>';
  1852. }
  1853. else if (item.goto == "ham@localhost") {
  1854. item.goto = '<span class="badge fs-6 bg-success">' + lang.goto_ham + '</span>';
  1855. }
  1856. if (item.in_primary_domain !== "") {
  1857. item.domain = '<i data-domainname="' + item.domain + '" class="bi bi-info-circle-fill alias-domain-info text-info" data-bs-toggle="tooltip" title="' + lang.target_domain + ': ' + item.in_primary_domain + '"></i> ' + item.domain;
  1858. }
  1859. });
  1860. return json;
  1861. }
  1862. },
  1863. columns: [
  1864. {
  1865. // placeholder, so checkbox will not block child row toggle
  1866. title: '',
  1867. data: null,
  1868. searchable: false,
  1869. orderable: false,
  1870. defaultContent: '',
  1871. responsivePriority: 1
  1872. },
  1873. {
  1874. title: '',
  1875. data: 'chkbox',
  1876. searchable: false,
  1877. orderable: false,
  1878. defaultContent: '',
  1879. responsivePriority: 2
  1880. },
  1881. {
  1882. title: 'ID',
  1883. data: 'id',
  1884. responsivePriority: 3,
  1885. defaultContent: ''
  1886. },
  1887. {
  1888. title: lang.alias,
  1889. data: 'address',
  1890. responsivePriority: 4,
  1891. defaultContent: ''
  1892. },
  1893. {
  1894. title: lang.target_address,
  1895. data: 'goto',
  1896. defaultContent: ''
  1897. },
  1898. {
  1899. title: lang.domain,
  1900. data: 'domain',
  1901. defaultContent: '',
  1902. responsivePriority: 5,
  1903. },
  1904. {
  1905. title: lang.bcc_destinations,
  1906. data: 'bcc_dest',
  1907. defaultContent: ''
  1908. },
  1909. {
  1910. title: lang.sogo_visible,
  1911. data: 'sogo_visible',
  1912. defaultContent: '',
  1913. render: function(data, type){
  1914. return 1==data?'<i class="bi bi-check-lg"><span class="sorting-value">1</span></i>':0==data&&'<i class="bi bi-x-lg"><span class="sorting-value">0</span></i>';
  1915. }
  1916. },
  1917. {
  1918. title: lang.public_comment,
  1919. data: 'public_comment',
  1920. defaultContent: ''
  1921. },
  1922. {
  1923. title: lang.private_comment,
  1924. data: 'private_comment',
  1925. defaultContent: ''
  1926. },
  1927. {
  1928. title: lang.active,
  1929. data: 'active',
  1930. defaultContent: '',
  1931. responsivePriority: 6,
  1932. render: function (data, type) {
  1933. return 1==data?'<i class="bi bi-check-lg"><span class="sorting-value">1</span></i>':0==data&&'<i class="bi bi-x-lg"><span class="sorting-value">0</span></i>';
  1934. }
  1935. },
  1936. {
  1937. title: lang.action,
  1938. data: 'action',
  1939. className: 'dt-sm-head-hidden dt-data-w100 dtr-col-md dt-text-right',
  1940. responsivePriority: 5,
  1941. defaultContent: ''
  1942. },
  1943. ]
  1944. });
  1945. table.on('responsive-resize', function (e, datatable, columns){
  1946. hideTableExpandCollapseBtn('#tab-mbox-aliases', '#alias_table');
  1947. });
  1948. table.on( 'draw', function (){
  1949. $('#alias_table [data-bs-toggle="tooltip"]').tooltip();
  1950. });
  1951. }
  1952. function draw_aliasdomain_table() {
  1953. // just recalc width if instance already exists
  1954. if ($.fn.DataTable.isDataTable('#aliasdomain_table') ) {
  1955. $('#aliasdomain_table').DataTable().columns.adjust().responsive.recalc();
  1956. return;
  1957. }
  1958. var table = $('#aliasdomain_table').DataTable({
  1959. responsive: true,
  1960. processing: true,
  1961. serverSide: false,
  1962. stateSave: true,
  1963. pageLength: pagination_size,
  1964. dom: "<'row'<'col-sm-12 col-md-6'f><'col-sm-12 col-md-6'l>>" +
  1965. "tr" +
  1966. "<'row'<'col-sm-12 col-md-5'i><'col-sm-12 col-md-7'p>>",
  1967. language: lang_datatables,
  1968. initComplete: function(){
  1969. hideTableExpandCollapseBtn('#tab-domain-aliases', '#aliasdomain_table');
  1970. },
  1971. ajax: {
  1972. type: "GET",
  1973. url: "/api/v1/get/alias-domain/all",
  1974. dataSrc: function(json){
  1975. $.each(json, function (i, item) {
  1976. item.alias_domain = escapeHtml(item.alias_domain);
  1977. item.action = '<div class="btn-group">' +
  1978. '<a href="/edit/aliasdomain/' + encodeURIComponent(item.alias_domain) + '" class="btn btn-sm btn-xs-lg btn-xs-third btn-secondary"><i class="bi bi-pencil-fill"></i> ' + lang.edit + '</a>' +
  1979. '<a href="#" data-action="delete_selected" data-id="single-alias-domain" data-api-url="delete/alias-domain" data-item="' + encodeURIComponent(item.alias_domain) + '" class="btn btn-sm btn-xs-lg btn-xs-third btn-danger"><i class="bi bi-trash"></i> ' + lang.remove + '</a>' +
  1980. '<a href="#dnsInfoModal" class="btn btn-sm btn-xs-lg btn-xs-third btn-info" data-bs-toggle="modal" data-domain="' + encodeURIComponent(item.alias_domain) + '"><i class="bi bi-globe2"></i> DNS</a></div>' +
  1981. '</div>';
  1982. item.chkbox = '<input type="checkbox" class="form-check-input" data-id="alias-domain" name="multi_select" value="' + encodeURIComponent(item.alias_domain) + '" />';
  1983. if(item.parent_is_backupmx == '1') {
  1984. item.target_domain = '<span><a href="/edit/domain/' + item.target_domain + '">' + item.target_domain + '</a> <div class="badge fs-6 bg-warning">' + lang.alias_domain_backupmx + '</div></span>';
  1985. } else {
  1986. item.target_domain = '<span><a href="/edit/domain/' + item.target_domain + '">' + item.target_domain + '</a></span>';
  1987. }
  1988. });
  1989. return json;
  1990. }
  1991. },
  1992. columns: [
  1993. {
  1994. // placeholder, so checkbox will not block child row toggle
  1995. title: '',
  1996. data: null,
  1997. searchable: false,
  1998. orderable: false,
  1999. defaultContent: '',
  2000. responsivePriority: 1
  2001. },
  2002. {
  2003. title: '',
  2004. data: 'chkbox',
  2005. searchable: false,
  2006. orderable: false,
  2007. defaultContent: '',
  2008. responsivePriority: 2
  2009. },
  2010. {
  2011. title: lang.alias,
  2012. data: 'alias_domain',
  2013. responsivePriority: 3,
  2014. defaultContent: ''
  2015. },
  2016. {
  2017. title: lang.target_domain,
  2018. data: 'target_domain',
  2019. responsivePriority: 4,
  2020. defaultContent: ''
  2021. },
  2022. {
  2023. title: lang.active,
  2024. data: 'active',
  2025. defaultContent: '',
  2026. render: function (data, type) {
  2027. return 1==data?'<i class="bi bi-check-lg"><span class="sorting-value">1</span></i>':0==data&&'<i class="bi bi-x-lg"><span class="sorting-value">0</span></i>';
  2028. }
  2029. },
  2030. {
  2031. title: lang.action,
  2032. data: 'action',
  2033. className: 'dt-sm-head-hidden dt-data-w100 dtr-col-md dt-text-right',
  2034. responsivePriority: 5,
  2035. defaultContent: ''
  2036. },
  2037. ]
  2038. });
  2039. table.on('responsive-resize', function (e, datatable, columns){
  2040. hideTableExpandCollapseBtn('#tab-domain-aliases', '#aliasdomain_table');
  2041. });
  2042. }
  2043. function draw_sync_job_table() {
  2044. // just recalc width if instance already exists
  2045. if ($.fn.DataTable.isDataTable('#sync_job_table') ) {
  2046. $('#sync_job_table').DataTable().columns.adjust().responsive.recalc();
  2047. return;
  2048. }
  2049. var table = $('#sync_job_table').DataTable({
  2050. responsive: true,
  2051. processing: true,
  2052. serverSide: false,
  2053. stateSave: true,
  2054. pageLength: pagination_size,
  2055. dom: "<'row'<'col-sm-12 col-md-6'f><'col-sm-12 col-md-6'l>>" +
  2056. "tr" +
  2057. "<'row'<'col-sm-12 col-md-5'i><'col-sm-12 col-md-7'p>>",
  2058. language: lang_datatables,
  2059. order: [[2, 'desc']],
  2060. initComplete: function(){
  2061. hideTableExpandCollapseBtn('#tab-syncjobs', '#sync_job_table');
  2062. },
  2063. ajax: {
  2064. type: "GET",
  2065. url: "/api/v1/get/syncjobs/all/no_log",
  2066. dataSrc: function(json){
  2067. $.each(json, function (i, item) {
  2068. item.log = '<a href="#syncjobLogModal" data-bs-toggle="modal" data-syncjob-id="' + encodeURIComponent(item.id) + '">' + lang.open_logs + '</a>'
  2069. item.user2 = escapeHtml(item.user2);
  2070. if (!item.exclude > 0) {
  2071. item.exclude = '-';
  2072. } else {
  2073. item.exclude = '<code>' + escapeHtml(item.exclude) + '</code>';
  2074. }
  2075. item.server_w_port = escapeHtml(item.user1) + '@' + escapeHtml(item.host1) + ':' + escapeHtml(item.port1);
  2076. item.action = '<div class="btn-group">' +
  2077. '<a href="/edit/syncjob/' + item.id + '" class="btn btn-sm btn-xs-lg btn-xs-half btn-secondary"><i class="bi bi-pencil-fill"></i> ' + lang.edit + '</a>' +
  2078. '<a href="#" data-action="delete_selected" data-id="single-syncjob" data-api-url="delete/syncjob" data-item="' + item.id + '" class="btn btn-sm btn-xs-lg btn-xs-half btn-danger"><i class="bi bi-trash"></i> ' + lang.remove + '</a>' +
  2079. '</div>';
  2080. item.chkbox = '<input type="checkbox" class="form-check-input" data-id="syncjob" name="multi_select" value="' + item.id + '" />';
  2081. if (item.is_running == 1) {
  2082. item.is_running = '<span id="active-script" class="badge fs-6 bg-success">' + lang.running + '</span>';
  2083. } else {
  2084. item.is_running = '<span id="inactive-script" class="badge fs-6 bg-warning">' + lang.waiting + '</span>';
  2085. }
  2086. if (!item.last_run > 0) {
  2087. item.last_run = lang.waiting;
  2088. }
  2089. if (item.success == null) {
  2090. item.success = '-';
  2091. item.exit_status = '';
  2092. } else {
  2093. item.success = '<i class="text-' + (item.success == 1 ? 'success' : 'danger') + ' bi bi-' + (item.success == 1 ? 'check-lg' : 'x-lg') + '"></i>';
  2094. }
  2095. if (lang['syncjob_'+item.exit_status]) {
  2096. item.exit_status = lang['syncjob_'+item.exit_status];
  2097. } else if (item.success != '-') {
  2098. item.exit_status = lang.syncjob_check_log;
  2099. }
  2100. item.exit_status = item.success + ' ' + item.exit_status;
  2101. });
  2102. return json;
  2103. }
  2104. },
  2105. columns: [
  2106. {
  2107. // placeholder, so checkbox will not block child row toggle
  2108. title: '',
  2109. data: null,
  2110. searchable: false,
  2111. orderable: false,
  2112. defaultContent: '',
  2113. responsivePriority: 1
  2114. },
  2115. {
  2116. title: '',
  2117. data: 'chkbox',
  2118. searchable: false,
  2119. orderable: false,
  2120. defaultContent: '',
  2121. responsivePriority: 2
  2122. },
  2123. {
  2124. title: 'ID',
  2125. data: 'id',
  2126. responsivePriority: 3,
  2127. defaultContent: ''
  2128. },
  2129. {
  2130. title: lang.owner,
  2131. data: 'user2',
  2132. responsivePriority: 4,
  2133. defaultContent: ''
  2134. },
  2135. {
  2136. title: 'Server',
  2137. data: 'server_w_port',
  2138. defaultContent: ''
  2139. },
  2140. {
  2141. title: lang.last_run,
  2142. data: 'last_run',
  2143. defaultContent: ''
  2144. },
  2145. {
  2146. title: lang.syncjob_last_run_result,
  2147. data: 'exit_status',
  2148. defaultContent: ''
  2149. },
  2150. {
  2151. title: 'Log',
  2152. data: 'log',
  2153. defaultContent: ''
  2154. },
  2155. {
  2156. title: lang.active,
  2157. data: 'active',
  2158. defaultContent: '',
  2159. render: function (data, type) {
  2160. return 1==data?'<i class="bi bi-check-lg"><span class="sorting-value">1</span></i>':0==data&&'<i class="bi bi-x-lg"><span class="sorting-value">0</span></i>';
  2161. }
  2162. },
  2163. {
  2164. title: lang.status,
  2165. data: 'is_running',
  2166. defaultContent: ''
  2167. },
  2168. {
  2169. title: lang.excludes,
  2170. data: 'exclude',
  2171. defaultContent: '',
  2172. className: 'none'
  2173. },
  2174. {
  2175. title: lang.mins_interval,
  2176. data: 'mins_interval',
  2177. defaultContent: '',
  2178. className: 'none'
  2179. },
  2180. {
  2181. title: lang.action,
  2182. data: 'action',
  2183. className: 'dt-sm-head-hidden dt-data-w100 dtr-col-md dt-text-right',
  2184. responsivePriority: 5,
  2185. defaultContent: ''
  2186. },
  2187. ]
  2188. });
  2189. table.on('responsive-resize', function (e, datatable, columns){
  2190. hideTableExpandCollapseBtn('#tab-syncjobs', '#sync_job_table');
  2191. });
  2192. }
  2193. function draw_filter_table() {
  2194. // just recalc width if instance already exists
  2195. if ($.fn.DataTable.isDataTable('#filter_table') ) {
  2196. $('#filter_table').DataTable().columns.adjust().responsive.recalc();
  2197. return;
  2198. }
  2199. var table = $('#filter_table').DataTable({
  2200. responsive: true,
  2201. autoWidth: false,
  2202. processing: true,
  2203. serverSide: false,
  2204. stateSave: true,
  2205. pageLength: pagination_size,
  2206. dom: "<'row'<'col-sm-12 col-md-6'f><'col-sm-12 col-md-6'l>>" +
  2207. "tr" +
  2208. "<'row'<'col-sm-12 col-md-5'i><'col-sm-12 col-md-7'p>>",
  2209. language: lang_datatables,
  2210. order: [[2, 'desc']],
  2211. initComplete: function(){
  2212. hideTableExpandCollapseBtn('#tab-filters', '#filter_table');
  2213. },
  2214. ajax: {
  2215. type: "GET",
  2216. url: "/api/v1/get/filters/all",
  2217. dataSrc: function(json){
  2218. $.each(json, function (i, item) {
  2219. if (item.active == 1) {
  2220. item.active = '<span id="active-script" class="badge fs-6 bg-success">' + lang.active + '</span>';
  2221. } else {
  2222. item.active = '<span id="inactive-script" class="badge fs-6 bg-warning">' + lang.inactive + '</span>';
  2223. }
  2224. item.script_desc = escapeHtml(item.script_desc);
  2225. item.script_data = '<pre class="text-break" style="margin:0px">' + escapeHtml(item.script_data) + '</pre>'
  2226. item.filter_type = '<div class="badge fs-6 bg-secondary">' + item.filter_type.charAt(0).toUpperCase() + item.filter_type.slice(1).toLowerCase() + '</div>'
  2227. item.action = '<div class="btn-group">' +
  2228. '<a href="/edit/filter/' + item.id + '" class="btn btn-sm btn-xs-lg btn-xs-half btn-secondary"><i class="bi bi-pencil-fill"></i> ' + lang.edit + '</a>' +
  2229. '<a href="#" data-action="delete_selected" data-id="single-filter" data-api-url="delete/filter" data-item="' + encodeURIComponent(item.id) + '" class="btn btn-sm btn-xs-lg btn-xs-half btn-danger"><i class="bi bi-trash"></i> ' + lang.remove + '</a>' +
  2230. '</div>';
  2231. item.chkbox = '<input type="checkbox" class="form-check-input" data-id="filter_item" name="multi_select" value="' + item.id + '" />'
  2232. });
  2233. return json;
  2234. }
  2235. },
  2236. columns: [
  2237. {
  2238. // placeholder, so checkbox will not block child row toggle
  2239. title: '',
  2240. data: null,
  2241. searchable: false,
  2242. orderable: false,
  2243. defaultContent: '',
  2244. responsivePriority: 1
  2245. },
  2246. {
  2247. title: '',
  2248. data: 'chkbox',
  2249. searchable: false,
  2250. orderable: false,
  2251. defaultContent: '',
  2252. responsivePriority: 2
  2253. },
  2254. {
  2255. title: 'ID',
  2256. data: 'id',
  2257. responsivePriority: 2,
  2258. defaultContent: ''
  2259. },
  2260. {
  2261. title: lang.active,
  2262. data: 'active',
  2263. responsivePriority: 3,
  2264. defaultContent: ''
  2265. },
  2266. {
  2267. title: 'Type',
  2268. data: 'filter_type',
  2269. responsivePriority: 4,
  2270. defaultContent: ''
  2271. },
  2272. {
  2273. title: lang.owner,
  2274. data: 'username',
  2275. defaultContent: ''
  2276. },
  2277. {
  2278. title: lang.description,
  2279. data: 'script_desc',
  2280. defaultContent: ''
  2281. },
  2282. {
  2283. title: 'Script',
  2284. data: 'script_data',
  2285. defaultContent: '',
  2286. className: 'none'
  2287. },
  2288. {
  2289. title: lang.action,
  2290. data: 'action',
  2291. className: 'dt-sm-head-hidden dt-data-w100 dtr-col-md dt-text-right',
  2292. responsivePriority: 5,
  2293. defaultContent: ''
  2294. },
  2295. ]
  2296. });
  2297. table.on('responsive-resize', function (e, datatable, columns){
  2298. hideTableExpandCollapseBtn('#tab-filters', '#filter_table');
  2299. });
  2300. };
  2301. function hideTableExpandCollapseBtn(tab, table){
  2302. if ($(table).hasClass('collapsed'))
  2303. $(tab).find(".table_collapse_option").show();
  2304. else
  2305. $(tab).find(".table_collapse_option").hide();
  2306. }
  2307. function filterByDomain(json, column, table){
  2308. var tableId = $(table.table().container()).attr('id');
  2309. // Create the `select` element
  2310. var select = $('<select class="btn btn-sm btn-xs-lg btn-light text-start mx-2"><option value="">'+lang.all_domains+'</option></select>')
  2311. .insertBefore(
  2312. $('#'+tableId+' .dataTables_filter > label > input')
  2313. )
  2314. .on( 'change', function(){
  2315. table.column(column)
  2316. .search($(this).val())
  2317. .draw();
  2318. });
  2319. // get all domains
  2320. var domains = [];
  2321. json.forEach(obj => {
  2322. Object.entries(obj).forEach(([key, value]) => {
  2323. if(key === 'domain') {
  2324. domains.push(value)
  2325. }
  2326. });
  2327. });
  2328. // get unique domain list
  2329. domains = domains.filter(function(value, index, array) {
  2330. return array.indexOf(value) === index;
  2331. });
  2332. // add domains to select
  2333. domains.forEach(function(domain) {
  2334. select.append($('<option>' + domain + '</option>'));
  2335. });
  2336. }
  2337. // detect element visibility changes
  2338. function onVisible(element, callback) {
  2339. $(document).ready(function() {
  2340. let element_object = document.querySelector(element);
  2341. if (element_object === null) return;
  2342. let observer = new IntersectionObserver((entries, observer) => {
  2343. entries.forEach(entry => {
  2344. if(entry.intersectionRatio > 0) {
  2345. callback(element_object);
  2346. observer.unobserve(element_object);
  2347. }
  2348. });
  2349. })
  2350. observer.observe(element_object);
  2351. });
  2352. }
  2353. // Load only if the tab is visible
  2354. onVisible("[id^=domain_table]", () => draw_domain_table());
  2355. onVisible("[id^=templates_domain_table]", () => draw_templates_domain_table());
  2356. onVisible("[id^=mailbox_table]", () => draw_mailbox_table());
  2357. onVisible("[id^=templates_mbox_table]", () => draw_templates_mbox_table());
  2358. onVisible("[id^=resource_table]", () => draw_resource_table());
  2359. onVisible("[id^=alias_table]", () => draw_alias_table());
  2360. onVisible("[id^=aliasdomain_table]", () => draw_aliasdomain_table());
  2361. onVisible("[id^=sync_job_table]", () => draw_sync_job_table());
  2362. onVisible("[id^=filter_table]", () => draw_filter_table());
  2363. onVisible("[id^=bcc_table]", () => draw_bcc_table());
  2364. onVisible("[id^=recipient_map_table]", () => draw_recipient_map_table());
  2365. onVisible("[id^=tls_policy_table]", () => draw_tls_policy_table());
  2366. });