JFIF  H H (ICC_PROFILE   0 mntrRGB XYZ acsp   - desc trXYZ d gXYZ x bXYZ  rTRC  (gTRC  (bTRC  (wtpt  cprt  بV7eudakt!Q ,*RGPQNČzŬb 5666p z"c83''Mq6Gitql@90.ۚAcN|li:9蠃p/^ZnLx84v;[#$ nh'c32o8Ɛ5KAv*_?nX?pyֆ̈́#z23F0Oe> {Gu.V (C'h/o%>x1X r:(>}{ycX8b]U:dOMsVAp'Z3'3E-ybj:>jOvUw#2cl~@gFCjțbz ^:-tdfj{XTh8aUM^+dAl"(KK m1$$ XKKqržoqg V FF#pG~:]֦!!Ң:pC+ AzӬ].t`='h_/} @L\,x㌼z԰+J-v+Y['8' % X q=[4Sj~4ݢ#dʂēRL5kX؊>l:t\baBA\Q38( ө:&$ 'L#d{qH>*5;jDo ˷YmԈ*[9*5tUf%3= GUW\'AR_W4_P պ -|4RFJZv0d[ˠzJ|PU8;鯌 'VcL,κ>*eb)f,0"j1 1v՘;bJ++COz7%>NU,=z\cEVK>Ic7} .jHn;^觱GHI HVǂO:ߊ{mSV?K|@ AiAT`2j 1~K8’$ ~]=9ឦG *9EMּm5Xf9Qĸ}i D%+t+;F: v:-&h_rD|! Ә;Zl븂':C&ҀaeKkm6 uT".}J&\ hciB2B+T7t?EPþЌmAF\lc2ЊABmE,cն\QJ]d5 `O Y@8?lx#KiI&Ri1fR2f1N%_g*TӨ??N:}+לɀh٭qL,ʈBrcuBmz ̢TV^ 뙏8' ufUX3㓏>NG:/;Hp饕B1K /%iɫ VQ%:_ -1oL?Roa\i^F|W*Na)P X#y㯨z+Cح\вjirm*dWҡQbBȨi'%NEb?'[h=`OiU϶u nR}GW4fVJmiR~J|l%m'%"LW V27NsXb?_={s}ij4Ý=SNjxFV"ԎI(E)]ӝЖm[4 m`5-7Wf󪥎bZKa#Vb%KY5T$y`46̼p C7HM'l{Oi +Pw~j,S5T4(FԨ;A`*HJTPgt(6/cg5U1@Qb8Y!rBzOQKF+6v%=~XDPpWc_-:߈#c坣CW1:^Q 06Ӭq@ Dj$ UW$?9F\cSM5=2>hב\,()JBk; J#j徻W(p=oQD #UMhU*Fc ?N=nF5Ӑ12w05Z뀩4ڣ霅uC1y%nJ8Ԑ*crR 9W=H9,A׻,.ZFb QEGVNs, q';OMmbtNVqOw*֙kPѬ؈XJIӯEWok+R{%j; Yx 7&&,LԜYbw"lI(*`۹F AS- #$413)Qpڤ3RxOJ$cP]viuq {kyN.- B,@󪳪ڸAor%X0UNb9 򍕑7)*233|Rnb@q|EUý$!7&["XOy ~ƓtADhP]mG파9p=ԜZ]ӭሎOeyq !bI GU:5~FoL ST[е$]$g*w]!;m@ޠ&IUڬ{҄բ-.SmҒ` vU"oL;'5s"W)@äL1i}^Y5$+Pv0o HU @ȓsQM)?M\4Q $2;g WJ/NwFJGD: y όMfW!QUZ%azҳDK_XhM^rԝ^!d'<#ﴛO{/F?+$ Y' wg'$ljGAH7l4xѶc}I*esg~;ͤt@B2iB'9C a8fTR: %NO@ m3sv w .@濾 ,FYrT0mUW_v>>d[A6ڊx:YTLHvӺ!nSD}>[mET0_,'C]pjVᅷPDZ[-V0`>}ܟpmֻ2O6O*ݹXHSN(J /+1՟#(P*gEO#w&j6?;ڡ)+U]l\/{莄*I/9<'$'#'yt/&-\\WPL`/p9qa'e¨E] fAAEYnGtm,ϮwXT>AaN#FjŵjQFdq^<H?yJ܃2*3 T4ЧH**W;(ꭽ¾Pf=eyA4FJ6{e]JqOCf#3SJf iMM\ iT$rG8$9>2:M)Q#NKe&"E8.z<mHk?#t˒A]; G0H:f!i! j{1m}o7u;$99Ӱ\ncz:zALq޶wyKT<4X,'!Y;Ͱ6q GM~_~܂}t>(zl}:r L9 fe}.-R*<`c6oܛ=prҽGB)nQ%)s*&i΍%—Zb{m[NNkbwBw Q*dF HP iܛ; aV68j}\eIGI'͔B;yA :^bn-m#@S6ˎr ;~cmƻgU:X6G%[gc{]c4)fpsgY˅>*"1}2<175)]V5)kdkM~`΂:{4nGPTTb   뎱϶w FFᓂG8>zF_H9_rDl:ҶH5Z!Bj.yk}erb:SOT]!ǎ?n:HεZsyztn[7NZ#UQO$.J#]Cr#YX9c<'$z 9 .$$PnDSn 2u5X g\ ?|Aᬰⶵ >>bE)Cb-ruMc׺*,\)`^m ge\k.۫8گoK1gWMpU޻zI=EErz:#6--/Wm\z8מ0x tA_c?Ծc^MژIMyO>l0ċ}t7[\ʲ9̜m_a[姯rְjP\kx1'CdmvF70e+m-]a?ݝKuSMUm 8f Yb!)2Z.UD \~:ܽ8zR̪Kcbs&ߦ1$, w\gc3F$iU#<`:I4{w.2aQ$EXNo?Gm NN rE$#Jn҉!AH'zePzRog8u(tJP߁Z.pÐ͢Aռ65Xsyvm 6RW7W;|0 >OүG@ٳ<>omԼ()kZJlK,F 4)snOQ{u㌏= Ao,ծ?eKBzG 6e6 f|CU _4C[j͕M8,%emM8\ cv COwTGi _94BDf%'ns8MPc&-y"8R_j 3a+z+N 9QlDQ40E VۋrH2I_YO',:뿉WNHvﵐ0B}na*E zUbN#0e"f.Q H5"-HVn=+ # Eiy- v8=g`o[ 鼛2.D^QeB ؅qϿRC~ B+Jۍ8 4*ӖΝ1R BI\ 1[0 I9y)Y " 7]6qg\ vP  s= Ѭ֕)פE< c`ϷU9W,: ?y1hsU(T ge/룮JA]|4aZVAIeIhBI!l$3![qHnw\7R{oM/ִ>5& gwjFE dc@K:V&W/k+=Yk[ @fU5zzmFȖH,[ n-dc wd[z"g4ϘRr0`B8_; #$^Zo5KZYKj GY%s"!a[9I2TF-w#a]˒Itٮei_FpVЧ૱W3eCi7 "}HApG>h֝5i T٧- '`dX1AF$$ޙ_Z]ڷTC Uy JGO} >A"5a> ZUR -Z\9 jrWݖQRݳ*ļ]$ڵXq=/w z\II#{ӭl^;F_R쵎[ָ[gKKͰoQ )W녕іs*kuzŨQde`WU_KLE~"g r<2GyއL(-VY -Z(IU0 |\;8C mhl:̄DkYHOk|:*DY tsس |zrO;񍃌sT31=jwyШ^nZHm_G̮0W󿓹S;_$mٛIDV=f-H}U]HA*vԶ3\Wh*I#$@6x^OZC&JU 16 XD*if&BDGFYYP[KLX uX .Z hq Ghb8M#Mqt\c> aT 00=㎨ʕGQԪR,ĜI9zӦJO3Rn`C5܊@QO1N.ؔ"I\YÖĐHdL\}IP~jm$ y; :ZGZVJv =&*UF#``R`*S+p\=) ҭ9k̮Ršx0'**ԑLkɺk+zJb#:|MZ ?j$ݼ &X)$6FY6ѕ/; J*nlC*ų_ ԕ{_6:\47ڷs4RmĊ=z *ʪXT[]5Bl#a-˙bv8@H|Rwe9A%5&M%Z02TN)&&GfM 儀oŒM;=.//k~ E"a9/3y,>lj>ZXy&εYP&h gec<``]!}i'c KQulFIʓ_\T58(+cJq~ [dgmm/`Xڙhtkq ו$"c[PVY[uɜ&#몵"ȾqC"ÜȔ!<Mj8u-dx*gϫtTLdKlaWڭ\~|7u`h(w֋cL=˼=FvcGs}зUBSМ;FI;Q$8+V|[CS쮙1%YP Q% LVVK+&,cIb]Vyi ~h?yF4"5As-F ݆x55P&E:W@f;}Gy^]U ITki 1 d﫠*cNh' cؗYnsL:b?H :kM~@8#Iqɔ~:f]P*i]H'fjhxTҗ1O:^t$1]UXz&tODT>(^s&3#N_/x-䬦? ~vU-W$4'ӎvRG|jySW?u4(1 G[ِ22jʎhrmoյشgRͮ%ϟѬ9 oR  n-&F-@hgY_qN;"2 !KJ  šA^, "aG8`=14=5Mqk>U@UT :RgjrKF.O$I9'=i}._ One Hat Cyber Team
  • Your IP: 216.73.216.182
  • Server IP: 104.21.4.18
  • Server: Linux vmi1569040.contaboserver.net 5.15.0-25-generic #25-Ubuntu SMP Wed Mar 30 15:54:22 UTC 2022 x86_64
  • Server Software: LiteSpeed
  • PHP Version: 8.1.28
  • Buat File | Buat Folder
View File Name : main.js
'; popupData.content += "
"; popupData.content += ""; popupData.message = app.lang.task_stop_timer; var $popupHTML = system_popup(popupData); $popupHTML.attr("id", "timer-select-task"); init_ajax_search( "tasks", "#timer_add_task_id", undefined, admin_url + "tasks/ajax_search_assign_task_to_timer" ); return false; } $(e).addClass("disabled"); var data = {}; data.task_id = task_id; data.timer_id = timer_id; data.note = $("body").find("#timesheet_note").val(); if (!data.note) { data.note = ""; } var taskModalVisible = $("#task-modal").is(":visible"); var reqUrl = admin_url + "tasks/timer_tracking?single_task=" + taskModalVisible; if (adminStop) { reqUrl += "&admin_stop=" + adminStop; } $.post(reqUrl, data).done(function (response) { response = JSON.parse(response); // Timer action, stopping from staff/member/id if ($("body").hasClass("member")) { window.location.reload(); } if (taskModalVisible) { _task_append_html(response.taskHtml); } if ($timerSelectTask.is(":visible")) { $timerSelectTask.find(".system-popup-close").click(); } _init_timers_top_html(JSON.parse(response.timers)); $(".popover-top-timer-note").popover("hide"); reload_tasks_tables(); }); } // Init task modal and get data from server function init_task_modal(task_id, comment_id) { var queryStr = ""; var $leadModal = $("#lead-modal"); var $taskAddEditModal = $("#_task_modal"); if ($leadModal.is(":visible")) { queryStr += "?opened_from_lead_id=" + $leadModal.find('input[name="leadid"]').val(); $leadModal.modal("hide"); } else if ($taskAddEditModal.attr("data-lead-id") != undefined) { queryStr += "?opened_from_lead_id=" + $taskAddEditModal.attr("data-lead-id"); } requestGet("tasks/get_task_data/" + task_id + queryStr) .done(function (response) { _task_append_html(response); if (typeof comment_id != "undefined") { setTimeout(function () { $('[data-task-comment-href-id="' + comment_id + '"]').click(); }, 1000); } }) .fail(function (data) { $("#task-modal").modal("hide"); alert_float("danger", data.responseText); }); } // General function to append task html returned from request function _task_append_html(html) { var $taskModal = $("#task-modal"); $taskModal.find(".data").html(html); //init_tasks_checklist_items(false, task_id); recalculate_checklist_items_progress(); do_task_checklist_items_height(); setTimeout(function () { $taskModal.modal("show"); // Init_tags_input is trigged too when task modal is shown // This line prevents triggering twice. if ($taskModal.is(":visible")) { init_tags_inputs(); } init_form_reminder("task"); fix_task_modal_left_col_height(); // Show the comment area on mobile when task modal is opened // Because the user may want only to upload file, but if the comment textarea is not focused the dropzone won't be shown if (is_mobile()) { init_new_task_comment(true); } }, 150); } // Tracking stats modal from task single function task_tracking_stats(id) { requestGet("tasks/task_tracking_stats/" + id).done(function (response) { $("
", { id: "tracking-stats", }) .appendTo("body") .html(response); $("#task-tracking-stats-modal").modal("toggle"); }); } // Fetches all staff timers and append to DOM function init_timers() { requestGetJSON("tasks/get_staff_started_timers").done(function (response) { _init_timers_top_html(response); }); } // Top started timers dropdown init html data with class function _init_timers_top_html(data) { var $tt = $("#top-timers"); var $ttIcon = $("#top-timers").find(".icon-started-timers"); data.total_timers > 0 ? $ttIcon.removeClass("hide").html(data.total_timers) : $ttIcon.addClass("hide"); data.total_timers > 0 ? $("#top-timers").find("svg").addClass("tw-animate-spin") : $("#top-timers").find("svg").removeClass("tw-animate-spin"); $("#started-timers-top").html(data.html); } // Init task edit comment function edit_task_comment(id) { var edit_wrapper = $('[data-edit-comment="' + id + '"]'); edit_wrapper.next().addClass("hide"); edit_wrapper.removeClass("hide"); tinymce.remove("#task_comment_" + id); var editorConfig = _simple_editor_config(); editorConfig.auto_focus = "task_comment_" + id; editorConfig.toolbar_sticky = true; init_editor("#task_comment_" + id, editorConfig); tinymce.triggerSave(); } // Cancel editing commment after clicked on edit href function cancel_edit_comment(id) { var edit_wrapper = $('[data-edit-comment="' + id + '"]'); tinymce.remove('[data-edit-comment="' + id + '"] textarea'); edit_wrapper.addClass("hide"); edit_wrapper.next().removeClass("hide"); } // Save task edited comment function save_edited_comment(id, task_id) { tinymce.triggerSave(); var data = {}; data.id = id; data.task_id = task_id; data.content = $('[data-edit-comment="' + id + '"]') .find("textarea") .val(); if (is_ios()) { data.no_editor = true; } $.post(admin_url + "tasks/edit_comment", data).done(function (response) { response = JSON.parse(response); if (response.success === true || response.success == "true") { alert_float("success", response.message); _task_append_html(response.taskHtml); } else { cancel_edit_comment(id); } tinymce.remove('[data-edit-comment="' + id + '"] textarea'); }); } // Fix task single modal height to be on both sides the same function fix_task_modal_left_col_height() { if (!is_mobile()) { $("body") .find(".task-single-col-left") .css( "min-height", $("body").find(".task-single-col-right").outerHeight(true) + "px" ); } } // Updates task when action performed form kan ban area eq status changed. function tasks_kanban_update(ui, object) { if (object === ui.item.parent()[0]) { var status = $(ui.item.parent()[0]).attr("data-task-status-id"); var data = { order: [], status: status, }; $.each($(ui.item.parent()[0]).find("[data-task-id]"), function (idx, el) { var id = $(el).attr("data-task-id"); if (id) { data.order.push([id, idx + 1]); } }); task_mark_as(status, $(ui.item).attr("data-task-id")); check_kanban_empty_col("[data-task-id]"); setTimeout(function () { $.post(admin_url + "tasks/update_order", data).done(function (response) { update_kan_ban_total_when_moving(ui, data.status); tasks_kanban(); }); }, 200); } } // Init tasks kan ban function tasks_kanban() { init_kanban("tasks/kanban", tasks_kanban_update, ".tasks-status", 240, 360); } // Task single edit description with inline editor, used from task single modal function edit_task_inline_description(e, id) { tinyMCE.remove("#task_view_description"); if ($(e).hasClass("editor-initiated")) { $(e).removeClass("editor-initiated"); return; } $(e).addClass("editor-initiated"); $.Shortcuts.stop(); tinymce.init({ branding: false, toolbar: false, menubar: false, inline: true, cache_suffix: '?v='+app.version, selector: "#task_view_description", theme: "silver", directionality: isRTL == "true" ? "rtl" : "", auto_focus: "task_view_description", plugins: ['quickbars', 'link', 'table', (isRTL == "true" ? " directionality" : "")], contextmenu: "link table paste pastetext", quickbars_insert_toolbar: "quicktable", quickbars_selection_toolbar: "bold italic | quicklink h2 h3 blockquote", table_default_styles: { width: "100%", }, setup: function (editor) { editor.on("blur", function (e) { if (editor.isDirty()) { $.post(admin_url + "tasks/update_task_description/" + id, { description: editor.getContent(), }); } setTimeout(function () { editor.remove(); $.Shortcuts.start(); }, 500); }); }, }); } // Tasks bulk actions action function tasks_bulk_action(event) { if (confirm_delete()) { var ids = [], data = {}, mass_delete = $("#mass_delete").prop("checked"); if (mass_delete == false || typeof mass_delete == "undefined") { data.status = $("#move_to_status_tasks_bulk_action").val(); var assignees = $("#task_bulk_assignees"); data.assignees = assignees.length ? assignees.selectpicker("val") : ""; var tags_bulk = $("#tags_bulk"); data.tags = tags_bulk.length ? tags_bulk.tagit("assignedTags") : ""; var milestone = $("#task_bulk_milestone"); data.milestone = milestone.length ? milestone.selectpicker("val") : ""; data.billable = $("#task_bulk_billable").val(); data.billable = typeof data.billable == "undefined" ? "" : data.billable; data.priority = $("#task_bulk_priority").val(); data.priority = typeof data.priority == "undefined" ? "" : data.priority; if ( data.status === "" && data.priority === "" && data.tags === "" && data.assignees === "" && data.milestone === "" && data.billable === "" ) { return; } } else { data.mass_delete = true; } var rows = $($("#tasks_bulk_actions").attr("data-table")).find("tbody tr"); $.each(rows, function () { var checkbox = $($(this).find("td").eq(0)).find("input"); if (checkbox.prop("checked") === true) { ids.push(checkbox.val()); } }); data.ids = ids; $(event).addClass("disabled"); setTimeout(function () { $.post(admin_url + "tasks/bulk_action", data).done(function () { window.location.reload(); }); }, 200); } } function load_small_table_item(id, selector, input_name, url, table) { var _tmpID = $('input[name="' + input_name + '"]').val(); // Check if id passed from url, hash is prioritized becuase is last if (_tmpID !== "" && !window.location.hash) { id = _tmpID; // Clear the current id value in case user click on the left sidebar credit_note_ids $('input[name="' + input_name + '"]').val(""); } else { // check first if hash exists and not id is passed, becuase id is prioritized if (window.location.hash && !id) { id = window.location.hash.substring(1); //Puts hash in variable, and removes the # character } } if (typeof id == "undefined" || id === "") { return; } destroy_dynamic_scripts_in_element($(selector)); if (!$("body").hasClass("small-table")) { toggle_small_view(table, selector); } $('input[name="' + input_name + '"]').val(id); do_hash_helper(id); $(selector).load(admin_url + url + "/" + id) $("html, body").animate( { scrollTop: $(selector).offset().top + (is_mobile() ? 150 : 0), }, 600 ); } // Init single invoice function init_invoice(id) { load_small_table_item( id, "#invoice", "invoiceid", "invoices/get_invoice_data_ajax", ".table-invoices" ); } // Init single credit note function init_credit_note(id) { load_small_table_item( id, "#credit_note", "credit_note_id", "credit_notes/get_credit_note_data_ajax", ".table-credit-notes" ); } // Init single estimate function init_estimate(id) { load_small_table_item( id, "#estimate", "estimateid", "estimates/get_estimate_data_ajax", ".table-estimates" ); } // Init single proposal function init_proposal(id) { load_small_table_item( id, "#proposal", "proposal_id", "proposals/get_proposal_data_ajax", ".table-proposals" ); } function init_expense(id) { load_small_table_item( id, "#expense", "expenseid", "expenses/get_expense_data_ajax", ".table-expenses" ); } // Clear billing and shipping inputs for invoice,estimate etc... function clear_billing_and_shipping_details() { for (var f in billingAndShippingFields) { if (billingAndShippingFields[f].indexOf("country") > -1) { $('select[name="' + billingAndShippingFields[f] + '"]').selectpicker( "val", "" ); } else { $('input[name="' + billingAndShippingFields[f] + '"]').val(""); $('textarea[name="' + billingAndShippingFields[f] + '"]').val(""); } if (billingAndShippingFields[f] == "billing_country") { $('input[name="include_shipping"]').prop("checked", false); $('input[name="include_shipping"]').change(); } } init_billing_and_shipping_details(); } // Init billing and shipping details for invoice, estimate etc... function init_billing_and_shipping_details() { var _f; var include_shipping = $('input[name="include_shipping"]').prop("checked"); for (var f in billingAndShippingFields) { _f = ""; if (billingAndShippingFields[f].indexOf("country") > -1) { _f = $("#" + billingAndShippingFields[f] + " option:selected").data( "subtext" ); } else if ( billingAndShippingFields[f].indexOf("shipping_street") > -1 || billingAndShippingFields[f].indexOf("billing_street") > -1 ) { if ($('textarea[name="' + billingAndShippingFields[f] + '"]').length) { _f = $('textarea[name="' + billingAndShippingFields[f] + '"]') .val() .replace(/(?:\r\n|\r|\n)/g, "
"); } } else { _f = $('input[name="' + billingAndShippingFields[f] + '"]').val(); } if (billingAndShippingFields[f].indexOf("shipping") > -1) { if (!include_shipping) { _f = ""; } } if (typeof _f == "undefined") { _f = ""; } _f = _f !== "" ? _f : "--"; $("." + billingAndShippingFields[f]).html(_f); } $("#billing_and_shipping_details").modal("hide"); } // Record payment function function record_payment(id) { if (typeof id == "undefined" || id === "") { return; } $("#invoice").load(admin_url + "invoices/record_invoice_payment_ajax/" + id); } function schedule_invoice_send(id) { $("#invoice").load(admin_url + "email_schedule_invoice/create/" + id); } function schedule_estimate_send(id) { $("#estimate").load(admin_url + "email_schedule_estimate/create/" + id); } function edit_invoice_scheduled_email(schedule_id) { $("#invoice").load(admin_url + "email_schedule_invoice/edit/" + schedule_id); } function edit_estimate_scheduled_email(schedule_id) { $("#estimate").load( admin_url + "email_schedule_estimate/edit/" + schedule_id ); } // Add item to preview function add_item_to_preview(id) { requestGetJSON("invoice_items/get_item_by_id/" + id).done(function ( response ) { clear_item_preview_values(); $('.main textarea[name="description"]').val(response.description); $('.main textarea[name="long_description"]').val( response.long_description.replace(/(<|<)br\s*\/*(>|>)/g, " ") ); _set_item_preview_custom_fields_array(response.custom_fields); $('.main input[name="quantity"]').val(1); var taxSelectedArray = []; if (response.taxname && response.taxrate) { taxSelectedArray.push(response.taxname + "|" + response.taxrate); } if (response.taxname_2 && response.taxrate_2) { taxSelectedArray.push(response.taxname_2 + "|" + response.taxrate_2); } $(".main select.tax").selectpicker("val", taxSelectedArray); $('.main input[name="unit"]').val(response.unit); var $currency = $("body").find( '.accounting-template select[name="currency"]' ); var baseCurency = $currency.attr("data-base"); var selectedCurrency = $currency.find("option:selected").val(); var $rateInputPreview = $('.main input[name="rate"]'); if (baseCurency == selectedCurrency) { $rateInputPreview.val(response.rate); } else { var itemCurrencyRate = response["rate_currency_" + selectedCurrency]; if (!itemCurrencyRate || parseFloat(itemCurrencyRate) === 0) { $rateInputPreview.val(response.rate); } else { $rateInputPreview.val(itemCurrencyRate); } } $(document).trigger({ type: "item-added-to-preview", item: response, item_type: "item", }); }); } function _set_item_preview_custom_fields_array(custom_fields) { var cf_act_as_inputs = [ "input", "number", "date_picker", "date_picker_time", "colorpicker", ]; for (var i = 0; i < custom_fields.length; i++) { var cf = custom_fields[i]; if ($.inArray(cf.type, cf_act_as_inputs) > -1) { var f = $('tr.main td[data-id="' + cf.id + '"] input'); // trigger change eq. for colorpicker f.val(cf.value).trigger("change"); } else if (cf.type == "textarea") { $('tr.main td[data-id="' + cf.id + '"] textarea').val(cf.value); } else if (cf.type == "select" || cf.type == "multiselect") { if (!empty(cf.value)) { var selected = cf.value.split(","); selected = selected.map(function (e) { return e.trim(); }); $('tr.main td[data-id="' + cf.id + '"] select').selectpicker( "val", selected ); } } else if (cf.type == "checkbox") { if (!empty(cf.value)) { var selected = cf.value.split(","); selected = selected.map(function (e) { return e.trim(); }); $.each(selected, function (i, e) { $( 'tr.main td[data-id="' + cf.id + '"] input[type="checkbox"][value="' + e + '"]' ).prop("checked", true); }); } } } } // Add task to preview function add_task_to_preview_as_item(id) { requestGetJSON("tasks/get_billable_task_data/" + id).done(function ( response ) { response.taxname = $("select.main-tax").selectpicker("val"); var previewArea = $(".main"); previewArea.find('textarea[name="description"]').val(response.name); previewArea .find('textarea[name="long_description"]') .val(response.description); previewArea.find('input[name="quantity"]').val(response.total_hours); previewArea.find('input[name="rate"]').val(response.hourly_rate); previewArea.find('input[name="unit"]').val(""); $('input[name="task_id"]').val(id); $(document).trigger({ type: "item-added-to-preview", item: response, item_type: "task", }); }); } // Clear the items added to preview function clear_item_preview_values(default_taxes) { // Get the last taxes applied to be available for the next item var last_taxes_applied = $("table.items tbody") .find("tr:last-child") .find("select") .selectpicker("val"); var previewArea = $(".main"); previewArea.find("textarea").val(""); // includes cf previewArea .find('td.custom_field input[type="checkbox"]') .prop("checked", false); // cf previewArea.find("td.custom_field input:not(:checkbox):not(:hidden)").val(""); // cf // not hidden for chkbox hidden helpers previewArea.find("td.custom_field select").selectpicker("val", ""); // cf previewArea.find('input[name="quantity"]').val(1); previewArea.find("select.tax").selectpicker("val", last_taxes_applied); previewArea.find('input[name="rate"]').val(""); previewArea.find('input[name="unit"]').val(""); $('input[name="task_id"]').val(""); $('input[name="expense_id"]').val(""); } // Append the added items to the preview to the table as items function add_item_to_table(data, itemid, merge_invoice, bill_expense) { // If not custom data passed get from the preview data = typeof data == "undefined" || data == "undefined" ? get_item_preview_values() : data; if ( data.description === "" && data.long_description === "" && data.rate === "" ) { return; } var table_row = ""; var item_key = lastAddedItemKey ? (lastAddedItemKey += 1) : $("body").find("tbody .item").length + 1; lastAddedItemKey = item_key; table_row += ''; table_row += ''; // Check if quantity is number if (isNaN(data.qty)) { data.qty = 1; } // Check if rate is number if (data.rate === "" || isNaN(data.rate)) { data.rate = 0; } var amount = data.rate * data.qty; var tax_name = "newitems[" + item_key + "][taxname][]"; $("body").append('
'); var regex = /]*>/gi; get_taxes_dropdown_template(tax_name, data.taxname).done(function ( tax_dropdown ) { // order input table_row += ''; table_row += ""; table_row += '"; table_row += '"; var custom_fields = $("tr.main td.custom_field"); var cf_has_required = false; if (custom_fields.length > 0) { $.each(custom_fields, function () { var cf = $(this).clone(); var cf_html = ""; var cf_field = $(this).find("[data-fieldid]"); var cf_name = "newitems[" + item_key + "][custom_fields][items][" + cf_field.attr("data-fieldid") + "]"; if (cf_field.is(":checkbox")) { var checked = $(this).find('input[type="checkbox"]:checked'); var checkboxes = cf.find('input[type="checkbox"]'); $.each(checkboxes, function (i, e) { var random_key = Math.random().toString(20).slice(2); $(this) .attr("id", random_key) .attr("name", cf_name) .next("label") .attr("for", random_key); if ($(this).attr("data-custom-field-required") == "1") { cf_has_required = true; } }); $.each(checked, function (i, e) { cf.find('input[value="' + $(e).val() + '"]').attr("checked", true); }); cf_html = cf.html(); } else if (cf_field.is("input") || cf_field.is("textarea")) { if (cf_field.is("input")) { cf.find("[data-fieldid]").attr("value", cf_field.val()); } else { cf.find("[data-fieldid]").html(cf_field.val()); } cf.find("[data-fieldid]").attr("name", cf_name); if ( cf.find("[data-fieldid]").attr("data-custom-field-required") == "1" ) { cf_has_required = true; } cf_html = cf.html(); } else if (cf_field.is("select")) { if ($(this).attr("data-custom-field-required") == "1") { cf_has_required = true; } var selected = $(this) .find("select[data-fieldid]") .selectpicker("val"); selected = typeof (selected != "array") ? new Array(selected) : selected; // Check if is multidimensional by multi-select customfield selected = selected[0].constructor === Array ? selected[0] : selected; var selectNow = cf.find("select"); var $wrapper = $("
"); selectNow.attr("name", cf_name); var $select = selectNow.clone(); $wrapper.append($select); $.each(selected, function (i, e) { $wrapper .find('select option[value="' + e + '"]') .attr("selected", true); }); cf_html = $wrapper.html(); } table_row += '' + cf_html + ""; }); } table_row += ''; if (!data.unit || typeof data.unit == "undefined") { data.unit = ""; } table_row += ''; table_row += ""; table_row += ''; table_row += '' + tax_dropdown + ""; table_row += '' + format_money(amount, true) + ""; table_row += ''; table_row += ""; $("table.items tbody").append(table_row); $(document).trigger({ type: "item-added-to-table", data: data, row: table_row, }); setTimeout(function () { calculate_total(); }, 15); var billed_task = $('input[name="task_id"]').val(); var billed_expense = $('input[name="expense_id"]').val(); if (billed_task !== "" && typeof billed_task != "undefined") { billed_tasks = billed_task.split(","); $.each(billed_tasks, function (i, obj) { $("#billed-tasks").append( hidden_input("billed_tasks[" + item_key + "][]", obj) ); }); } if (billed_expense !== "" && typeof billed_expense != "undefined") { billed_expenses = billed_expense.split(","); $.each(billed_expenses, function (i, obj) { $("#billed-expenses").append( hidden_input("billed_expenses[" + item_key + "][]", obj) ); }); } if ( $("#item_select").hasClass("ajax-search") && $("#item_select").selectpicker("val") !== "" ) { $("#item_select").prepend(""); } init_selectpicker(); init_datepicker(); init_color_pickers(); clear_item_preview_values(); reorder_items(); $("body").find("#items-warning").remove(); $("body").find(".dt-loader").remove(); $("#item_select").selectpicker("val", ""); if (cf_has_required && $(".invoice-form").length) { validate_invoice_form(); } else if (cf_has_required && $(".estimate-form").length) { validate_estimate_form(); } else if (cf_has_required && $(".proposal-form").length) { validate_proposal_form(); } else if (cf_has_required && $(".credit-note-form").length) { validate_credit_note_form(); } if (bill_expense == "undefined" || !bill_expense) { $('select[name="task_select"]') .find('[value="' + billed_task + '"]') .remove(); $('select[name="task_select"]').selectpicker("refresh"); } return true; }); return false; } // Get taxes dropdown selectpicker template function get_taxes_dropdown_template(name, taxname) { return $.post(admin_url + "misc/get_taxes_dropdown_template", { name: name, taxname: taxname, }); } // Custom function for deselecting selected value from ajax dropdown function deselect_ajax_search(e) { var $elm = $("select#" + $(e).attr("data-id")); $elm.data("AjaxBootstrapSelect").list.cache = {}; var $elmWrapper = $elm.parents(".bootstrap-select"); $elm .html("") .append('') .selectpicker("val", $elm.attr("multiple") == "multiple" ? [] : ""); $elmWrapper .removeClass("ajax-remove-values-option") .find(".ajax-clear-values") .remove(); setTimeout(function () { $elm.trigger("selected.cleared.ajax.bootstrap.select", e); $elm.trigger("change").data("AjaxBootstrapSelect").list.cache = {}; }, 50); } // Ajax project search but only for specific customer function init_ajax_project_search_by_customer_id(selector) { selector = typeof selector == "undefined" ? "#project_id.ajax-search" : selector; init_ajax_search("project", selector, { customer_id: function () { return $("#clientid").val(); }, }); } // Ajax project search select function init_ajax_projects_search(selector) { selector = typeof selector == "undefined" ? "#project_id.ajax-search" : selector; init_ajax_search("project", selector); } // Make items sortable with jquery sort plugin function init_items_sortable(preview_table) { var _items_sortable = $("#wrapper").find(".items tbody"); if (_items_sortable.length === 0) { return; } _items_sortable.sortable({ helper: fixHelperTableHelperSortable, handle: ".dragger", placeholder: "ui-placeholder", itemPath: "> tbody", itemSelector: "tr.sortable", items: "tr.sortable", update: function () { if (typeof preview_table == "undefined") { reorder_items(); } else { // If passed from the admin preview there is other function for re-ordering save_ei_items_order(); } }, sort: function (event, ui) { // Firefox fixer when dragging var $target = $(event.target); if (!/html|body/i.test($target.offsetParent()[0].tagName)) { var top = event.pageY - $target.offsetParent().offset().top - ui.helper.outerHeight(true) / 2; ui.helper.css({ top: top + "px", }); } }, }); } // Save the items from order from the admin preview function save_ei_items_order() { var table = $(".table.items-preview"); var rows = table.find("tbody tr"); var i = 1, type = table.attr("data-type"), order = [], _order_id, item_id; if (!type) { return false; } $.each(rows, function () { order.push([$(this).data("item-id"), i]); // update item number when reordering $(this).find("td.item_no").html(i); i++; }); setTimeout(function () { $.post(admin_url + "misc/update_ei_items_order/" + type, { data: order, }); }, 200); } // Reoder the items in table edit for estimate and invoices function reorder_items() { var rows = $(".table.has-calculations tbody tr.item"); var i = 1; $.each(rows, function () { $(this).find("input.order").val(i); i++; }); } // Get the preview main values function get_item_preview_values() { var response = {}; response.description = $('.main textarea[name="description"]').val(); response.long_description = $( '.main textarea[name="long_description"]' ).val(); response.qty = $('.main input[name="quantity"]').val(); response.taxname = $(".main select.tax").selectpicker("val"); response.rate = $('.main input[name="rate"]').val(); response.unit = $('.main input[name="unit"]').val(); return response; } // Calculate invoice total - NOT RECOMENDING EDIT THIS FUNCTION BECUASE IS VERY SENSITIVE function calculate_total() { if ($("body").hasClass("no-calculate-total")) { return false; } var calculated_tax, taxrate, item_taxes, row, _amount, _tax_name, taxes = {}, taxes_rows = [], subtotal = 0, total = 0, quantity = 1, total_discount_calculated = 0, rows = $(".table.has-calculations tbody tr.item"), discount_area = $("#discount_area"), adjustment = $('input[name="adjustment"]').val(), discount_percent = $('input[name="discount_percent"]').val(), discount_fixed = $('input[name="discount_total"]').val(), discount_total_type = $(".discount-total-type.selected"), discount_type = $('select[name="discount_type"]').val(); $(".tax-area").remove(); $.each(rows, function () { quantity = $(this).find("[data-quantity]").val(); if (quantity === "") { quantity = 1; $(this).find("[data-quantity]").val(1); } _amount = accounting.toFixed( $(this).find("td.rate input").val() * quantity, app.options.decimal_places ); _amount = parseFloat(_amount); $(this).find("td.amount").html(format_money(_amount, true)); subtotal += _amount; row = $(this); item_taxes = $(this).find("select.tax").selectpicker("val"); if (item_taxes) { $.each(item_taxes, function (i, taxname) { taxrate = row .find('select.tax [value="' + taxname + '"]') .data("taxrate"); calculated_tax = (_amount / 100) * taxrate; if (!taxes.hasOwnProperty(taxname)) { if (taxrate != 0) { _tax_name = taxname.split("|"); tax_row = '' + _tax_name[0] + "(" + taxrate + '%)'; $(discount_area).after(tax_row); taxes[taxname] = calculated_tax; } } else { // Increment total from this tax taxes[taxname] = taxes[taxname] += calculated_tax; } }); } }); // Discount by percent if ( discount_percent !== "" && discount_percent != 0 && discount_type == "before_tax" && discount_total_type.hasClass("discount-type-percent") ) { total_discount_calculated = (subtotal * discount_percent) / 100; } else if ( discount_fixed !== "" && discount_fixed != 0 && discount_type == "before_tax" && discount_total_type.hasClass("discount-type-fixed") ) { total_discount_calculated = discount_fixed; } $.each(taxes, function (taxname, total_tax) { if ( discount_percent !== "" && discount_percent != 0 && discount_type == "before_tax" && discount_total_type.hasClass("discount-type-percent") ) { total_tax_calculated = (total_tax * discount_percent) / 100; total_tax = total_tax - total_tax_calculated; } else if ( discount_fixed !== "" && discount_fixed != 0 && discount_type == "before_tax" && discount_total_type.hasClass("discount-type-fixed") ) { var t = (discount_fixed / subtotal) * 100; total_tax = total_tax - (total_tax * t) / 100; } total += total_tax; total_tax = format_money(total_tax); $("#tax_id_" + slugify(taxname)).html(total_tax); }); total = total + subtotal; // Discount by percent if ( discount_percent !== "" && discount_percent != 0 && discount_type == "after_tax" && discount_total_type.hasClass("discount-type-percent") ) { total_discount_calculated = (total * discount_percent) / 100; } else if ( discount_fixed !== "" && discount_fixed != 0 && discount_type == "after_tax" && discount_total_type.hasClass("discount-type-fixed") ) { total_discount_calculated = discount_fixed; } total = total - total_discount_calculated; adjustment = parseFloat(adjustment); // Check if adjustment not empty if (!isNaN(adjustment)) { total = total + adjustment; } var discount_html = "-" + format_money(total_discount_calculated); $('input[name="discount_total"]').val( accounting.toFixed(total_discount_calculated, app.options.decimal_places) ); // Append, format to html and display $(".discount-total").html(discount_html); $(".adjustment").html(format_money(adjustment)); $(".subtotal").html( format_money(subtotal) + hidden_input( "subtotal", accounting.toFixed(subtotal, app.options.decimal_places) ) ); $(".total").html( format_money(total) + hidden_input( "total", accounting.toFixed(total, app.options.decimal_places) ) ); $(document).trigger("sales-total-calculated"); } function exclude_tax_from_amount(tax_percent, total_amount) { totalTax = accounting.toFixed( (total_amount * tax_percent) / (100 + tax_percent), app.options.decimal_places ); return accounting.toFixed( total_amount - totalTax, app.options.decimal_places ); } // Deletes invoice items function delete_item(row, itemid) { $(row) .parents("tr") .addClass("animated fadeOut", function () { setTimeout(function () { $(row).parents("tr").remove(); calculate_total(); }, 50); }); // If is edit we need to add to input removed_items to track activity if (itemid && $('input[name="isedit"]').length > 0) { $("#removed-items").append(hidden_input("removed_items[]", itemid)); } } // Format money function function format_money(total, excludeSymbol) { if (typeof excludeSymbol != "undefined" && excludeSymbol) { return accounting.formatMoney(total, { symbol: "", }); } return accounting.formatMoney(total); } // Set the currency for accounting function init_currency(id, callback) { var $accountingTemplate = $("body").find(".accounting-template"); if ($accountingTemplate.length || id) { var selectedCurrencyId = !id ? $accountingTemplate.find('select[name="currency"]').val() : id; requestGetJSON("misc/get_currency/" + selectedCurrencyId).done(function ( currency ) { // Used for formatting money accounting.settings.currency.decimal = currency.decimal_separator; accounting.settings.currency.thousand = currency.thousand_separator; accounting.settings.currency.symbol = currency.symbol; accounting.settings.currency.format = currency.placement == "after" ? "%v %s" : "%s%v"; calculate_total(); if (callback) { callback(); } }); } } // Delete invoice attachment function delete_invoice_attachment(id) { if (confirm_delete()) { requestGet("invoices/delete_attachment/" + id) .done(function (success) { if (success == 1) { $("body") .find('[data-attachment-id="' + id + '"]') .remove(); init_invoice( $("body").find('input[name="_attachment_sale_id"]').val() ); } }) .fail(function (error) { alert_float("danger", error.responseText); }); } } // Delete credit note attachment function delete_credit_note_attachment(id) { if (confirm_delete()) { requestGet("credit_notes/delete_attachment/" + id) .done(function (success) { if (success == 1) { $("body") .find('[data-attachment-id="' + id + '"]') .remove(); init_credit_note( $("body").find('input[name="_attachment_sale_id"]').val() ); } }) .fail(function (error) { alert_float("danger", error.responseText); }); } } // Delete estimate attachment function delete_estimate_attachment(id) { if (confirm_delete()) { requestGet("estimates/delete_attachment/" + id) .done(function (success) { if (success == 1) { $("body") .find('[data-attachment-id="' + id + '"]') .remove(); var rel_id = $("body") .find('input[name="_attachment_sale_id"]') .val(); $("body").hasClass("estimates-pipeline") ? estimate_pipeline_open(rel_id) : init_estimate(rel_id); } }) .fail(function (error) { alert_float("danger", error.responseText); }); } } // Delete proposal attachment function delete_proposal_attachment(id) { if (confirm_delete()) { requestGet("proposals/delete_attachment/" + id) .done(function (success) { if (success == 1) { var rel_id = $("body") .find('input[name="_attachment_sale_id"]') .val(); $("body") .find('[data-attachment-id="' + id + '"]') .remove(); $("body").hasClass("proposals-pipeline") ? proposal_pipeline_open(rel_id) : init_proposal(rel_id); } }) .fail(function (error) { alert_float("danger", error.responseText); }); } } // Invoices quick total stats function init_invoices_total(manual) { if ($("#invoices_total").length === 0) { return; } var _inv_total_inline = $(".invoices-total-inline"); var _inv_total_href_manual = $(".invoices-total"); if ( $("body").hasClass("invoices-total-manual") && typeof manual == "undefined" && !_inv_total_href_manual.hasClass("initialized") ) { return; } if ( _inv_total_inline.length > 0 && _inv_total_href_manual.hasClass("initialized") ) { // On the next request won't be inline in case of currency change // Used on dashboard _inv_total_inline.removeClass("invoices-total-inline"); return; } _inv_total_href_manual.addClass("initialized"); var _years = $("body") .find('select[name="invoices_total_years"]') .selectpicker("val"); var years = []; $.each(_years, function (i, _y) { if (_y !== "") { years.push(_y); } }); var currency = $("body").find('select[name="total_currency"]').val(); var data = { currency: currency, years: years, init_total: true, }; var project_id = $('input[name="project_id"]').val(); var customer_id = $('.customer_profile input[name="userid"]').val(); if (typeof project_id != "undefined") { data.project_id = project_id; } else if (typeof customer_id != "undefined") { data.customer_id = customer_id; } $.post(admin_url + "invoices/get_invoices_total", data).done(function ( response ) { $("#invoices_total").html(response); }); } // Estimates quick total stats function init_estimates_total(manual) { if ($("#estimates_total").length === 0) { return; } var _est_total_href_manual = $(".estimates-total"); if ( $("body").hasClass("estimates-total-manual") && typeof manual == "undefined" && !_est_total_href_manual.hasClass("initialized") ) { return; } _est_total_href_manual.addClass("initialized"); var currency = $("body").find('select[name="total_currency"]').val(); var _years = $("body") .find('select[name="estimates_total_years"]') .selectpicker("val"); var years = []; $.each(_years, function (i, _y) { if (_y !== "") { years.push(_y); } }); var customer_id = ""; var project_id = ""; var _customer_id = $('.customer_profile input[name="userid"]').val(); var _project_id = $('input[name="project_id"]').val(); if (typeof _customer_id != "undefined") { customer_id = _customer_id; } else if (typeof _project_id != "undefined") { project_id = _project_id; } $.post(admin_url + "estimates/get_estimates_total", { currency: currency, init_total: true, years: years, customer_id: customer_id, project_id: project_id, }).done(function (response) { $("#estimates_total").html(response); }); } // Expenses quick total stats function init_expenses_total() { if ($("#expenses_total").length === 0) { return; } var currency = $("body").find('select[name="expenses_total_currency"]').val(); var _years = $("body") .find('select[name="expenses_total_years"]') .selectpicker("val"); var years = []; $.each(_years, function (i, _y) { if (_y !== "") { years.push(_y); } }); var customer_id = ""; var _customer_id = $('.customer_profile input[name="userid"]').val(); if (typeof customer_id != "undefined") { customer_id = _customer_id; } var project_id = ""; var _project_id = $('input[name="project_id"]').val(); if (typeof project_id != "undefined") { project_id = _project_id; } $.post(admin_url + "expenses/get_expenses_total", { currency: currency, init_total: true, years: years, customer_id: customer_id, project_id: project_id, }).done(function (response) { $("#expenses_total").html(response); }); } // Validate invoice add/edit form function validate_invoice_form(selector) { selector = typeof selector == "undefined" ? "#invoice-form" : selector; appValidateForm($(selector), { clientid: { required: { depends: function () { var customerRemoved = $("select#clientid").hasClass("customer-removed"); return !customerRemoved; }, }, }, date: "required", currency: "required", repeat_every_custom: { min: 1, }, number: { required: true, }, }); $("body") .find('input[name="number"]') .rules("add", { remote: { url: admin_url + "invoices/validate_invoice_number", type: "post", data: { number: function () { return $('input[name="number"]').val(); }, isedit: function () { return $('input[name="number"]').data("isedit"); }, original_number: function () { return $('input[name="number"]').data("original-number"); }, date: function () { return $('input[name="date"]').val(); }, }, }, messages: { remote: app.lang.invoice_number_exists, }, }); } function validate_credit_note_form(selector) { selector = typeof selector == "undefined" ? "#credit-note-form" : selector; appValidateForm($(selector), { clientid: { required: { depends: function () { var customerRemoved = $("select#clientid").hasClass("customer-removed"); return !customerRemoved; }, }, }, date: "required", currency: "required", number: { required: true, }, }); $("body") .find('input[name="number"]') .rules("add", { remote: { url: admin_url + "credit_notes/validate_number", type: "post", data: { number: function () { return $('input[name="number"]').val(); }, isedit: function () { return $('input[name="number"]').data("isedit"); }, original_number: function () { return $('input[name="number"]').data("original-number"); }, date: function () { return $(".credit_note input[name='date']").val(); }, }, }, messages: { remote: app.lang.credit_note_number_exists, }, }); } // Validates estimate add/edit form function validate_estimate_form(selector) { selector = typeof selector == "undefined" ? "#estimate-form" : selector; appValidateForm($(selector), { clientid: { required: { depends: function () { var customerRemoved = $("select#clientid").hasClass("customer-removed"); return !customerRemoved; }, }, }, date: "required", currency: "required", number: { required: true, }, }); $("body") .find('input[name="number"]') .rules("add", { remote: { url: admin_url + "estimates/validate_estimate_number", type: "post", data: { number: function () { return $('input[name="number"]').val(); }, isedit: function () { return $('input[name="number"]').data("isedit"); }, original_number: function () { return $('input[name="number"]').data("original-number"); }, date: function () { return $("body").find('.estimate input[name="date"]').val(); }, }, }, messages: { remote: app.lang.estimate_number_exists, }, }); } // Sort estimates in the pipeline view / switching sort type by click function estimates_pipeline_sort(type) { kan_ban_sort(type, estimate_pipeline); } // Sort proposals in the pipeline view / switching sort type by click function proposal_pipeline_sort(type) { kan_ban_sort(type, proposals_pipeline); } // Init estimates pipeline function estimate_pipeline() { init_kanban( "estimates/get_pipeline", estimates_pipeline_update, ".pipeline-status", 290, 360 ); } // Used when estimate is updated from pipeline. eq changed order or moved to another status function estimates_pipeline_update(ui, object) { if (object === ui.item.parent()[0]) { var data = { estimateid: $(ui.item).attr("data-estimate-id"), status: $(ui.item.parent()[0]).attr("data-status-id"), order: [], }; $.each( $(ui.item).parents(".pipeline-status").find("li"), function (idx, el) { var id = $(el).attr("data-estimate-id"); if (id) { data.order.push([id, idx + 1]); } } ); check_kanban_empty_col("[data-estimate-id]"); setTimeout(function () { $.post(admin_url + "estimates/update_pipeline", data).done(function ( response ) { update_kan_ban_total_when_moving(ui, data.status); estimate_pipeline(); }); }, 200); } } // Used when proposal is updated from pipeline. eq changed order or moved to another status function proposals_pipeline_update(ui, object) { if (object === ui.item.parent()[0]) { var data = { order: [], status: $(ui.item.parent()[0]).attr("data-status-id"), proposalid: $(ui.item).attr("data-proposal-id"), }; $.each( $(ui.item).parents(".pipeline-status").find("li"), function (idx, el) { var id = $(el).attr("data-proposal-id"); if (id) { data.order.push([id, idx + 1]); } } ); check_kanban_empty_col("[data-proposal-id]"); setTimeout(function () { $.post(admin_url + "proposals/update_pipeline", data).done(function ( response ) { update_kan_ban_total_when_moving(ui, data.status); proposals_pipeline(); }); }, 200); } } // Init proposals pipeline function proposals_pipeline() { init_kanban( "proposals/get_pipeline", proposals_pipeline_update, ".pipeline-status", 290, 360 ); } // Open single proposal in pipeline function proposal_pipeline_open(id) { if (id === "") { return; } requestGet("proposals/pipeline_open/" + id).done(function (response) { var visible = $(".proposal-pipeline-modal:visible").length > 0; $("#proposal").html(response); if (!visible) { $(".proposal-pipeline-modal").modal({ show: true, backdrop: "static", keyboard: false, }); } else { $("#proposal") .find(".modal.proposal-pipeline-modal") .removeClass("fade") .addClass("in") .css("display", "block"); } }); } // Estimate single open in pipeline function estimate_pipeline_open(id) { if (id === "") { return; } requestGet("estimates/pipeline_open/" + id).done(function (response) { var visible = $(".estimate-pipeline:visible").length > 0; $("#estimate").html(response); if (!visible) { $(".estimate-pipeline").modal({ show: true, backdrop: "static", keyboard: false, }); } else { $("#estimate") .find(".modal.estimate-pipeline") .removeClass("fade") .addClass("in") .css("display", "block"); } }); } // Delete estimate note function delete_sales_note(wrapper, id) { if (confirm_delete()) { requestGetJSON("misc/delete_note/" + id).done(function (response) { if (response.success === true || response.success == "true") { $(wrapper).parents(".sales-note-wrapper").remove(); var salesNotesWrapper = $("#sales-notes-wrapper"); var totalNotesNow = salesNotesWrapper.attr("data-total") - 1; var notesTotal = $(".notes-total"); salesNotesWrapper.attr("data-total", totalNotesNow); if (totalNotesNow <= 0) { notesTotal.addClass("hide"); } else { notesTotal.html('' + totalNotesNow + ""); } } }); } } // Get all estimate notes function get_sales_notes(id, controller) { requestGet(controller + "/get_notes/" + id).done(function (response) { $("#sales_notes_area").html(response); var totalNotesNow = $("#sales-notes-wrapper").attr("data-total"); if (totalNotesNow > 0) { $(".notes-total") .html('' + totalNotesNow + "") .removeClass("hide"); } }); } // Proposal merge field into the editor function insert_proposal_merge_field(field) { tinymce.activeEditor.execCommand("mceInsertContent", false, $(field).text()); } // Toggle full view for small tables like proposals function small_table_full_view() { $("#small-table").toggleClass("hide"); $(".small-table-right-col").toggleClass("col-md-12 col-md-7"); $(window).trigger("resize"); } // Used to update manually the prefix after invoice/estimate is created. function save_sales_number_settings(e) { var data = {}; data.prefix = $("body").find('input[name="s_prefix"]').val(); $.post($(e).data("url"), data).done(function (response) { response = JSON.parse(response); if (response.success && response.message) { alert_float("success", response.message); $("#prefix").html(data.prefix); } }); } // Prefix for invoices/estimates in case there is year. function do_prefix_year(date) { var date_array = _split_formatted_date_by_separator(date); if (typeof date_array != "undefined") { $.each(date_array, function (i, string) { if (string.length == 4) { var $pYear = $("#prefix_year"); if ($pYear.hasClass("format-n-yy")) { string = string.substr(-2); } else if ($pYear.hasClass("format-mm-yyyy")) { var month_index; if ( app.options.date_format == "d-m-Y" || app.options.date_format == "d/m/Y" || app.options.date_format == "Y-m-d" || app.options.date_format == "d.m.Y" ) { month_index = 1; } else if ( app.options.date_format == "m-d-Y" || app.options.date_format == "m.d.Y" || app.options.date_format == "m/d/Y" ) { month_index = 0; } $("#prefix_month").html(date_array[month_index]); } $pYear.html(string); } }); } } function unformat_date(date) { var date_array = _split_formatted_date_by_separator(date), // Y-m-d is default, see below commented code month_index = 1, year_index = 0, day_index = 2; if ( app.options.date_format == "d-m-Y" || app.options.date_format == "d/m/Y" || app.options.date_format == "d.m.Y" ) { day_index = 0; month_index = 1; year_index = 2; } else if ( /* else if (app.options.date_format == 'Y-m-d') { day_index = 2; month_index = 1; year_index = 0; }*/ app.options.date_format == "m-d-Y" || app.options.date_format == "m.d.Y" || app.options.date_format == "m/d/Y" ) { day_index = 1; month_index = 0; year_index = 2; } return ( date_array[year_index] + "-" + date_array[month_index] + "-" + date_array[day_index] ); } function _split_formatted_date_by_separator(date) { var date_array; if (date.indexOf(".") > -1) { date_array = date.split("."); } else if (date.indexOf("-") > -1) { date_array = date.split("-"); } else if (date.indexOf("/") > -1) { date_array = date.split("/"); } return date_array; } function init_tabs_scrollable() { // Not working fine on RTL if (isRTL != "true") { if ($(window).width() <= 768) { $("body").find(".toggle_view").remove(); } // Horinzontal tabs $(".horizontal-scrollable-tabs").horizontalTabs(); } else { $(".arrow-left, .arrow-right").css("display", "none"); $(".horizontal-scrollable-tabs").removeClass("horizontal-scrollable-tabs"); $(".nav-tabs-horizontal").removeClass("nav-tabs-horizontal"); } } function view_contact_consent(id) { requestGet("clients/consents/" + id).done(function (response) { $("#consent_data").html(response); initDataTableInline($("#consentHistoryTable")); $("#consentModal").modal("show"); }); } function view_lead_consent(id) { window.location.hash = "gdpr"; init_lead(id); } // Set single notification as read INLINE function set_notification_read_inline(id) { requestGet("misc/set_notification_read_inline/" + id).done(function () { var notification = $("body").find( '.notification-wrapper[data-notification-id="' + id + '"]' ); notification .find(".notification-handler") .removeClass("unread-notification"); notification.find(".not-mark-as-read-inline").tooltip("destroy").remove(); }); } // Marks all notifications as read INLINE function mark_all_notifications_as_read_inline() { requestGet("misc/mark_all_notifications_as_read_inline/").done(function () { var notification = $("body").find(".notification-wrapper"); notification .find(".notification-handler") .removeClass("unread-notification"); notification.find(".not-mark-as-read-inline").tooltip("destroy").remove(); }); } // Deletes activity for sales eq. invoices, estimates. function delete_sale_activity(id) { if (confirm_delete()) { requestGet("misc/delete_sale_activity/" + id).done(function () { $("body") .find('[data-sale-activity-id="' + id + '"]') .remove(); }); } } // View calendar custom single event function view_event(id) { if (typeof id == "undefined") { return; } $.post(admin_url + "utilities/view_event/" + id).done(function (response) { $("#event").html(response); $("#viewEvent").modal("show"); init_datepicker(); init_selectpicker(); validate_calendar_form(); }); } // Delete calendar event form function delete_event(id) { if (confirm_delete()) { requestGetJSON("utilities/delete_event/" + id).done(function (response) { if (response.success === true || response.success == "true") { window.location.reload(); } }); } } // Validate calendar event form function validate_calendar_form() { appValidateForm( $("body").find("._event form"), { title: "required", start: "required", reminder_before: "required", }, calendar_form_handler ); appValidateForm( $("body").find("#viewEvent form"), { title: "required", start: "required", reminder_before: "required", }, calendar_form_handler ); } // Handles calendar event saving function calendar_form_handler(form) { $.post(form.action, $(form).serialize()).done(function (response) { response = JSON.parse(response); if (response.success === true || response.success == "true") { alert_float("success", response.message); setTimeout(function () { var location = window.location.href; location = location.split("?"); window.location.href = location[0]; }, 500); } }); return false; } // Fetches notifications function fetch_notifications(callback) { requestGetJSON("misc/notifications_check").done(function (response) { var nw = notifications_wrapper; nw.html(response.html); var total = nw.find("ul.notifications").attr("data-total-unread"); document.title = total > 0 ? "(" + total + ") " + doc_initial_title : doc_initial_title; var nIds = response.notificationsIds; if (app.browser == "firefox" && nIds.length > 1) { var lastNotification = nIds[0]; nIds = []; nIds.push(lastNotification); } setTimeout(function () { if (nIds.length > 0) { $.each(nIds, function (i, notId) { var nSelector = 'li[data-notification-id="' + notId + '"]'; var $not = nw.find(nSelector); $.notify("", { title: app.lang.new_notification, body: $not.find(".notification-title").text(), requireInteraction: true, icon: $not.find(".notification-image").attr("src"), tag: notId, closeTime: app.options.dismiss_desktop_not_after != "0" ? app.options.dismiss_desktop_not_after * 1000 : null, }) .close(function () { requestGet("misc/set_desktop_notification_read/" + notId).done( function (response) { var $totalIndicator = nw.find(".icon-total-indicator"); nw.find( 'li[data-notification-id="' + notId + '"] .notification-box' ).removeClass("unread"); var currentTotalNotifications = $totalIndicator.text(); currentTotalNotifications = currentTotalNotifications.trim(); currentTotalNotifications = currentTotalNotifications - 1; if (currentTotalNotifications > 0) { document.title = "(" + currentTotalNotifications + ") " + doc_initial_title; $totalIndicator.html(currentTotalNotifications); } else { document.title = doc_initial_title; $totalIndicator.addClass("hide"); } } ); }) .click(function (e) { parent.focus(); window.focus(); setTimeout(function () { nw.find(nSelector + " .notification-link") .addClass("desktopClick") .click(); e.target.close(); }, 70); }); }); } }, 10); }); } function init_new_task_comment(manual) { if (tinymce.get('task_comment')) { tinymce.remove("#task_comment"); } if (typeof taskCommentAttachmentDropzone != "undefined") { taskCommentAttachmentDropzone.destroy(); } $("#dropzoneTaskComment").removeClass("hide"); $("#addTaskCommentBtn").removeClass("hide"); taskCommentAttachmentDropzone = new Dropzone( "#task-comment-form", appCreateDropzoneOptions({ uploadMultiple: true, clickable: "#dropzoneTaskComment", previewsContainer: ".dropzone-task-comment-previews", autoProcessQueue: false, addRemoveLinks: true, parallelUploads: 20, maxFiles: 20, paramName: "file", sending: function (file, xhr, formData) { formData.append( "taskid", $("#addTaskCommentBtn").attr("data-comment-task-id") ); if (tinyMCE.activeEditor) { formData.append("content", tinyMCE.activeEditor.getContent()); } else { formData.append("content", $("#task_comment").val()); } }, success: function (files, response) { response = JSON.parse(response); if ( this.getUploadingFiles().length === 0 && this.getQueuedFiles().length === 0 ) { _task_append_html(response.taskHtml); tinymce.remove("#task_comment"); } }, }) ); var editorConfig = _simple_editor_config(); editorConfig.toolbar_sticky = true if (typeof manual == "undefined" || manual === false) { editorConfig.auto_focus = true; } var taskid = $("#task-modal #taskid").val(); editorConfig.content_style = "span.mention {\ background-color: #eeeeee;\ padding: 3px;\ }"; editorConfig.setup = function (editor) { initializeTinyMceMentions(editor, function () { return $.getJSON( admin_url + "tasks/get_staff_names_for_mentions/" + taskid ) }) }; init_editor("#task_comment", editorConfig) } function initializeTinyMceMentions(editor, usersCallback) { if(!Object.hasOwn(editor, 'perfexCommands')) { editor.perfexCommands = {} } let cachedUsers = null; editor.perfexCommands.getUsersForMention = async function() { if(Array.isArray(cachedUsers)) { return cachedUsers } let users = await usersCallback() cachedUsers = users.map(u=>({ value: u.id.toString(), text: u.name, })); return cachedUsers }, editor.perfexCommands.insertMentionUser = function (id, name, rng) { // Insert in to the editor editor.selection.setRng(rng || 0) editor.insertContent(( '@' + name + " " )) } editor.ui.registry.addAutocompleter('mentions', { trigger: '@', // the trigger character to open the autocompleter minChars: 0, // 0 to open the dropdown immediately after the @ is typed columns: 1, // must be 1 for text-based results // Retrieve the available users fetch: function (pattern) { return new Promise(resolve => resolve(editor.perfexCommands.getUsersForMention()) ) }, // Executed when user is selected from the dropdown onAction: function (autocompleteApi, rng, value) { editor.perfexCommands.getUsersForMention().then(users=> { let user = users.find(user=>user.value == value) editor.perfexCommands.insertMentionUser(value, user.text, rng) autocompleteApi.hide() }) }, }) } function init_ajax_search(type, selector, server_data, url) { var ajaxSelector = $("body").find(selector); if (ajaxSelector.length) { var options = { ajax: { url: typeof url == "undefined" ? admin_url + "misc/get_relation_data" : url, data: function () { var data = {}; data.type = type; data.rel_id = ""; data.q = "{{{q}}}"; if (typeof server_data != "undefined") { jQuery.extend(data, server_data); } return data; }, }, locale: { emptyTitle: app.lang.search_ajax_empty, statusInitialized: app.lang.search_ajax_initialized, statusSearching: app.lang.search_ajax_searching, statusNoResults: app.lang.not_results_found, searchPlaceholder: app.lang.search_ajax_placeholder, currentlySelected: app.lang.currently_selected, }, requestDelay: 500, cache: false, preprocessData: function (processData) { var bs_data = []; var len = processData.length; for (var i = 0; i < len; i++) { var tmp_data = { value: processData[i].id, text: processData[i].name, }; if (processData[i].subtext) { tmp_data.data = { subtext: processData[i].subtext, }; } bs_data.push(tmp_data); } return bs_data; }, preserveSelectedPosition: "after", preserveSelected: true, }; if (ajaxSelector.data("empty-title")) { options.locale.emptyTitle = ajaxSelector.data("empty-title"); } ajaxSelector.selectpicker().ajaxSelectPicker(options); } } // Used for email template URL function merge_field_format_url(url, node, on_save, name) { // Merge fields url if (url && url.indexOf("%7B") > -1 && url.indexOf("%7D") > -1) { url = url.replaceAll("%7B", "{").replaceAll("%7D", "}"); } return url; } function salesGoogleDriveSave(pickData) { salesExtenalFileUpload(pickData, "gdrive"); } function leadExternalFileUpload(files, externalType, leadId) { $.post(admin_url + "leads/add_external_attachment", { files: files, lead_id: leadId, external: externalType, }).done(function () { init_lead_modal_data(leadId); }); } function taskExternalFileUpload(files, externalType, taskId) { $.post(admin_url + "tasks/add_external_attachment", { files: files, task_id: taskId, external: externalType, }).done(function () { init_task_modal(taskId); }); } function salesExtenalFileUpload(files, externalType) { var _data = {}; _data.rel_id = $("body").find('input[name="_attachment_sale_id"]').val(); _data.type = $("body").find('input[name="_attachment_sale_type"]').val(); _data.files = files; _data.external = externalType; $.post(admin_url + "misc/add_sales_external_attachment", _data).done( function () { if (_data.type == "estimate") { if ($("body").hasClass("estimates-pipeline")) { estimate_pipeline_open(_data.rel_id); } else { init_estimate(_data.rel_id); } } else if (_data.type == "proposal") { if ($("body").hasClass("proposals-pipeline")) { proposal_pipeline_open(_data.rel_id); } else { init_proposal(_data.rel_id); } } else { if (typeof window["init_" + _data.type] == "function") { window["init_" + _data.type](_data.rel_id); } } $("#sales_attach_file").modal("hide"); } ); } function set_search_history(history) { var $searchHistory = $("#search-history"); var historyHtml = ""; for (var i = 0; i < history.length; i++) { historyHtml += '
  • ' + history[i] + '
  • '; } $searchHistory.html(historyHtml); } // General helper function for $.get ajax requests function requestGet(uri, params) { params = typeof params == "undefined" ? {} : params; var options = { type: "GET", url: uri.indexOf(admin_url) > -1 ? uri : admin_url + uri, }; return $.ajax($.extend({}, options, params)); } // General helper function for $.get ajax requests with dataType JSON function requestGetJSON(uri, params) { params = typeof params == "undefined" ? {} : params; params.dataType = "json"; return requestGet(uri, params); } // Templates Js function update_templates_count(type) { var count = $(".templates-wrapper").length; $(".total_templates").text(count); if (count === 0) { $(".total_templates").addClass("hide"); } else { $(".total_templates").removeClass("hide"); } } function get_templates(rel_type, rel_id) { if (rel_type === "proposals") { $("#proposal-templates").load( admin_url + "templates", { rel_type: rel_type, rel_id: rel_id, }, function () { update_templates_count(); } ); } else if (rel_type === "contracts") { $("#contract-templates").load( admin_url + "templates", { rel_type: rel_type, rel_id: rel_id, }, function () { update_templates_count(); } ); } } function add_template(rel_type, rel_id) { $("#modal-wrapper").load( admin_url + "templates/modal", { slug: "new", rel_type: rel_type, rel_id: rel_id, }, function () { if ($("#TemplateModal").is(":hidden")) { $("#TemplateModal").modal({ backdrop: "static", show: true, }); } appValidateForm($("#template-form"), { name: "required", }); tinymce.remove("#content"); init_editor("#content", { pagebreak_split_block: true, contextmenu: "link image inserttable | cell row column deletetable | paste copy | pagebreak", append_plugins: "pagebreak", }); } ); } function edit_template(rel_type, id, rel_id) { $("#modal-wrapper").load( admin_url + "templates/modal", { slug: "edit", id: id, rel_type: rel_type, rel_id: rel_id, }, function () { if ($("#TemplateModal").is(":hidden")) { $("#TemplateModal").modal({ backdrop: "static", show: true, }); } appValidateForm($("#template-form"), { name: "required", }); tinymce.remove("#content"); init_editor("#content", { pagebreak_split_block: true, contextmenu: "link image inserttable | cell row column deletetable | paste copy | pagebreak", append_plugins: "pagebreak", }); } ); } function delete_template(wrapper, rel_type, id) { if (confirm_delete()) { $.post(admin_url + "templates/delete/" + id).done(function (response) { response = JSON.parse(response); if (response.success === true || response.success == "true") { if (rel_type === "proposals") { $(wrapper).parents(".proposal-templates-wrapper").html(""); } else if (rel_type === "contracts") { $(wrapper).parents(".contract-templates-wrapper").html(""); } get_templates(rel_type); } }); } } function insert_template(wrapper, rel_type, id) { requestGetJSON(admin_url + "templates/index/" + id).done(function (response) { var data = response.data; tinymce.activeEditor.execCommand("mceInsertContent", false, data.content); if (rel_type == "proposals") { $('a[aria-controls="tab_proposal"]').click(); } else if (rel_type == "contracts") { $('a[aria-controls="tab_content"]').click(); } tinymce.activeEditor.focus(); }); } function retrieve_imap_folders(url, params) { var dfd = $.Deferred(); $("#folders-loader").addClass("spinning").removeClass("hidden"); $.post(url, params) .done(function (response) { response = JSON.parse(response); if (response.hasOwnProperty("alert_type")) { alert_float(response.alert_type, response.message); } else { var output = ""; var $folder = $("#folder"); var currentFolder = $folder.selectpicker("val"); response.forEach(function (folderName) { output += '"; }); $folder.html(output); $folder.selectpicker("refresh"); if (!currentFolder) { $folder.selectpicker("val", $folder.find("option:eq(0)")[0].value); } } dfd.resolve(response); }) .fail(function (error) { dfd.reject(error); }) .always(function () { $("#folders-loader").removeClass("spinning").addClass("hidden"); }); return dfd.promise(); } function add_batch_payment() { $("#modal-wrapper").load( admin_url + "payments/batch_payment_modal", function () { if ($("#batch-payment-modal").is(":hidden")) { $("#batch-payment-modal").modal({ backdrop: "static", show: true, }); } init_selectpicker(); init_datepicker(); var $filterByClientSelect = $("#batch-payment-filter"); $filterByClientSelect.on("changed.bs.select", function () { if ($filterByClientSelect.val() !== "") { $(".batch_payment_item").each(function () { if ($(this).data("clientid") == $filterByClientSelect.val()) { $(this).find("input, select").prop("disabled", false); $(this).removeClass("hide"); } else { $(this).addClass("hide"); $(this).find("input, select").prop("disabled", true); } }); } else { $(".batch_payment_item").each(function () { $(this).removeClass("hide"); $(this).find("input, select").prop("disabled", false); }); } }); appValidateForm($("#batch-payment-form"), {}); $(".batch_payment_item").each(function () { var invoiceLine = $(this).find('[name^="invoice"]'); invoiceLine .filter('select[name$="[paymentmode]"],input[name$="[amount]"]') .each(function () { var field = $(this); field.rules("add", { required: function () { var isRequired = false; var rowFields = field .closest(".batch_payment_item") .find("input, select"); rowFields .filter( 'select[name$="[paymentmode]"],input[name$="[transactionid]"],input[name$="[amount]"]' ) .each(function () { if ($(this).val() != "") { isRequired = true; } if ($(this).hasClass("selectpicker") && isRequired) { field.prop("required", true); $(this).selectpicker("refresh"); } }); return isRequired; }, }); }); }); } ); } /** * @DEPRECATED FUNCTIONS */ /** * @deprecated */ function initDatatableOffline(dt_table) { console.warn( '"initDatatableOffline" is deprecated, use "initDataTableInline" instead.' ); initDataTableInline(dt_table); } /** * @deprecated * @since 2.3.2 */ function init_currency_symbol() { console.warn( '"init_currency_symbol" is deprecated, use "init_currency" instead' ); init_currency(); }