diff --git a/modules/core/site.js b/modules/core/site.js index 592958d9b..aa1678562 100644 --- a/modules/core/site.js +++ b/modules/core/site.js @@ -435,7 +435,6 @@ Hm_Modal.prototype = { this.modalTitle.html(title); } }; - class Hm_Alert { constructor() { this.container = document.querySelector('.sys_messages'); @@ -2588,6 +2587,39 @@ function setupActionSnooze(callback) { $(document).on('change', '.nexter_input_snooze', callback); } +class Hm_Filter_Modal extends Hm_Modal { + constructor(current_account) { + super({ + size: "xl", + modalId: "myEditFilterModal", + }); + const save_filter = Hm_Filters.save_filter; + const modalContent = document.querySelector("#edit_filter_modal"); + if (modalContent) { + this.setContent(modalContent.innerHTML); + modalContent.remove(); + } else { + this.setContent("

Could not load filter editor

"); + } + + this.addFooterBtn("Save", "btn-primary ms-auto", async () => { + let result = save_filter(current_account); + if (result) { + Hm_Notices.show("Filter saved", "success"); + this.hide(); + } + }); + + this.addFooterBtn("Convert to code", "btn-warning", async () => { + let result = save_filter(current_account, true); + if (result) { + Hm_Notices.show("Filter saved", "success"); + this.hide(); + } + }); + } +} + document.addEventListener("show.bs.dropdown", function (event) { const currentToggle = event.target; @@ -2604,4 +2636,3 @@ document.addEventListener("show.bs.dropdown", function (event) { } }); }); - diff --git a/modules/imap/handler_modules.php b/modules/imap/handler_modules.php index 68746cb70..a208371b4 100644 --- a/modules/imap/handler_modules.php +++ b/modules/imap/handler_modules.php @@ -1933,6 +1933,11 @@ public function process() { $this->out('imap_accounts', $this->user_config->get('imap_servers'), array()); $this->out('show_pagination_links', $this->user_config->get('pagination_links_setting', true)); $this->out('auto_advance_email_enabled', $this->user_config->get('auto_advance_email_setting', true)); + + $details = Hm_IMAP_List::dump($form['imap_server_id']); + $mailbox_name = $details['name']; + + $part = false; $prefetch = false; if (isset($this->request->post['imap_msg_part']) && preg_match("/[0-9\.]+/", $this->request->post['imap_msg_part'])) { @@ -1996,6 +2001,7 @@ public function process() { $this->session->set(sprintf('reply_details_imap_%s_%s_%s', $form['imap_server_id'], $form['folder'], $form['imap_msg_uid']), array('ts' => time(), 'msg_struct' => $msg_struct_current, 'msg_text' => ($save_reply_text ? $msg_text : ''), 'msg_headers' => $msg_headers)); } + $this->out('mailbox_name', $mailbox_name); } } } diff --git a/modules/imap/output_modules.php b/modules/imap/output_modules.php index 73d556181..9dcc4df2e 100644 --- a/modules/imap/output_modules.php +++ b/modules/imap/output_modules.php @@ -181,6 +181,9 @@ protected function output() { */ class Hm_Output_filter_message_headers extends Hm_Output_Module { protected function output() { + + $mailbox_name = $this->get('mailbox_name'); + if ($this->get('msg_headers')) { $txt = ''; $small_headers = array('subject', 'x-snoozed', 'date', 'from', 'to', 'reply-to', 'cc', 'flags'); @@ -420,6 +423,57 @@ protected function output() { $txt .= ' '.$this->trans('Block Sender').''; } } + + if ($this->get('sieve_filters_enabled')) { + $txt .= '' + . ''; + } + $txt .= '' . $this->trans('Show Source') . ''; $txt .= ''; diff --git a/modules/imap/setup.php b/modules/imap/setup.php index 19fd4e966..d15154038 100644 --- a/modules/imap/setup.php +++ b/modules/imap/setup.php @@ -337,6 +337,7 @@ 'do_not_flag_as_read_on_open' => array(FILTER_VALIDATE_BOOLEAN, false), 'ajax_imap_folders_permissions' => array(FILTER_UNSAFE_RAW, FILTER_REQUIRE_ARRAY), 'move_responses' => array(FILTER_UNSAFE_RAW, FILTER_REQUIRE_ARRAY), + 'mailbox_name' => FILTER_SANITIZE_FULL_SPECIAL_CHARS, ), 'allowed_get' => array( diff --git a/modules/imap/site.js b/modules/imap/site.js index 2106b3245..241dcc163 100644 --- a/modules/imap/site.js +++ b/modules/imap/site.js @@ -960,6 +960,87 @@ var imap_move_copy = function(e, action, context) { return false; }; +$(function () { + $(document).on("submit", "#create-filter-form", function (e) { + e.preventDefault(); + const current_account = $(this).attr("account"); + + const edit_filter_modal = new Hm_Filter_Modal(current_account); + hm_sieve_button_events(edit_filter_modal); + edit_filter_modal.setTitle("Add Filter for message like this"); + const add_filter_condition = Hm_Filters.add_filter_condition; + const add_filter_action = Hm_Filters.add_filter_action; + + const $form = $(this); + const $btn = $form.find("#create_filter").prop("disabled", true); + const data = {}; + + if ($form.find("#use_from").is(":checked")) + data["from"] = $form.find('input[name="from"]').val(); + if ($form.find("#use_to").is(":checked")) + data["to"] = $form.find('input[name="to"]').val(); + if ($form.find("#use_subject").is(":checked")) + data["subject"] = $form.find('input[name="subject"]').val(); + if ($form.find("#use_reply").is(":checked")) + data["reply-to"] = $form.find('input[name="reply-to"]').val(); + + if ($.isEmptyObject(data)) { + Hm_Notices.show( + "Please check at least one condition to create a filter.", + "danger" + ); + $btn.prop("disabled", false); + return; + } + + edit_filter_modal.open(); + + const allFields = hm_sieve_condition_fields(); + const availableFields = [ + ...allFields.Message.map((f) => f.name), + ...allFields.Header.map((f) => f.name), + ]; + + for (const [key, value] of Object.entries(data)) { + // If key is not in available fields, skip it + if (!availableFields.includes(key)) { + continue; + } + + add_filter_condition(); + + const $lastRow = $(".sieve_list_conditions_modal tr").last(); + const $selectField = $lastRow.find( + ".add_condition_sieve_filters" + ); + const $selectOp = $lastRow.find(".condition_options"); + const $inputVal = $lastRow.find( + 'input[name="sieve_selected_option_value[]"]' + ); + $selectField.val(key); + $selectOp.val("Contains"); + $inputVal.val(value); + } + + if (data["reply-to"]) { + add_filter_action("autoreply"); + + const $lastRow = $(".filter_actions_modal_table tr").last(); + const $select = $lastRow.find(".sieve_actions_select"); + $select.val("autoreply").trigger("change"); + + // Focus the input field for the message + const $input = $lastRow.find( + 'input[name="sieve_selected_action_value[]"]' + ); + if ($input.length) { + $input.focus(); + } + } + + }); +}); + var imap_perform_move_copy = function(dest_id, context, action = null) { if (!action) { action = $('.move_to_type').val(); diff --git a/modules/sievefilters/modules.php b/modules/sievefilters/modules.php index 632a0c862..92f913b8a 100644 --- a/modules/sievefilters/modules.php +++ b/modules/sievefilters/modules.php @@ -1162,13 +1162,25 @@ protected function output() { /** * @subpackage sievefilters/output */ -class Hm_Output_sievefilters_settings_start extends Hm_Output_Module { +class Hm_Output_sievefilters_title_start extends Hm_Output_Module { protected function output() { $socked_connected = $this->get('socket_connected', false); $res = '
'.$this->trans('Filters').'
'; $res .= '
'; $res .= '
'; - $res .= get_classic_filter_modal_content(); + return $res; + } +} + +/** + * @subpackage sievefilters/output + */ +class Hm_Output_sievefilters_settings_start extends Hm_Output_Module +{ + protected function output() + { + + $res = get_classic_filter_modal_content(); $res .= get_script_modal_content(); return $res; } diff --git a/modules/sievefilters/setup.php b/modules/sievefilters/setup.php index 7f22bdc6b..4813c008f 100644 --- a/modules/sievefilters/setup.php +++ b/modules/sievefilters/setup.php @@ -18,8 +18,11 @@ add_handler('ajax_imap_debug', 'sieve_connect', true, 'imap', 'imap_connect', 'after'); // sieve filter +add_output('sieve_filters', 'sievefilters_title_start', true, 'sievefilters', 'content_section_start', 'after'); add_output('sieve_filters', 'sievefilters_settings_start', true, 'sievefilters', 'content_section_start', 'after'); +add_output('message', 'sievefilters_settings_start', true, 'sievefilters', 'content_section_start', 'after'); add_output('ajax_hm_folders', 'sievefilters_settings_link', true, 'sievefilters', 'settings_menu_end', 'before'); +add_output('message', 'sievefilters_settings_link', true, 'sievefilters', 'settings_menu_end', 'before'); setup_base_ajax_page('ajax_account_sieve_filters', 'core'); add_handler('ajax_account_sieve_filters', 'settings_load_imap', true, 'sievefilters', 'load_user_data', 'after'); add_handler('ajax_account_sieve_filters', 'load_account_sieve_filters', true, 'sievefilters', 'settings_load_imap', 'after'); @@ -145,6 +148,7 @@ 'ajax_sieve_toggle_script_state', 'ajax_list_block_sieve', 'message_list', + 'message', 'ajax_account_sieve_filters', 'ajax_block_account_sieve_filters', ), diff --git a/modules/sievefilters/site.js b/modules/sievefilters/site.js index b189bbabb..843656a37 100644 --- a/modules/sievefilters/site.js +++ b/modules/sievefilters/site.js @@ -2,6 +2,10 @@ * Possible Sieve fields * @type {{Message: [{name: string, options: string[], type: string, selected: boolean},{name: string, options: string[], type: string},{name: string, options: string[], type: string}], Header: [{name: string, options: string[], type: string},{name: string, options: string[], type: string},{name: string, options: string[], type: string},{name: string, options: string[], type: string}]}} */ +let is_editing_script = false; +let current_editing_script_name = ""; +// let hm_sieve_current_account = ""; +var hm_sieve_current_account = ""; var hm_sieve_condition_fields = function() { return { 'Message': [ @@ -186,6 +190,798 @@ var hm_sieve_possible_actions = function() { ]; }; +const Hm_Filters = (function (my) { + my.save_filter = function (imap_account, gen_script = false) { + let is_editing_filter = false; + let current_editing_filter_name = ""; + function ordinal_number(n) { + let ord = "th"; + + if (n % 10 == 1 && n % 100 != 11) { + ord = "st"; + } else if (n % 10 == 2 && n % 100 != 12) { + ord = "nd"; + } else if (n % 10 == 3 && n % 100 != 13) { + ord = "rd"; + } + + return n + ord; + } + let validation_failed = false; + let conditions_parsed = []; + let actions_parsed = []; + + let conditions = $("select[name^=sieve_selected_conditions_field]") + .map(function (idx, elem) { + return $(elem).val(); + }) + .get(); + + let conditions_type = $("select[name^=sieve_selected_conditions_options]") + .map(function (idx, elem) { + return $(elem).val(); + }) + .get(); + + let conditions_value = $("input[name^=sieve_selected_option_value]") + .map(function (idx, elem) { + return $(elem).val(); + }) + .get(); + + let conditions_extra_value = $( + "input[name^=sieve_selected_extra_option_value]" + ) + .map(function (idx, elem) { + return $(elem).val(); + }) + .get(); + + let idx = 0; + if (conditions.length === 0) { + Hm_Notices.show("You must provide at least one condition", "warning"); + return false; + } + + conditions.forEach(function (elem, key) { + if (conditions_value[idx] === "" && conditions_value[idx] !== "none") { + let order = ordinal_number(key + 1); + Hm_Notices.show( + "The " + order + " condition (" + elem + ") must be provided", + "warning" + ); + validation_failed = true; + } + conditions_parsed.push({ + condition: elem, + type: conditions_type[idx], + extra_option: conditions[idx].extra_option, + extra_option_value: conditions_extra_value[idx], + value: conditions_value[idx], + }); + idx++; + }); + + let actions_type = $("select[name^=sieve_selected_actions]") + .map(function (idx, elem) { + return $(elem).val(); + }) + .get(); + + let actions_value = $("[name^=sieve_selected_action_value]") + .map(function (idx, elem) { + return $(elem).val(); + }) + .get(); + + let actions_field_type = $("[name^=sieve_selected_action_value]") + .map(function (idx, elem) { + return $(elem).attr("type"); + }) + .get(); + + let actions_extra_value = $( + "input[name^=sieve_selected_extra_action_value]" + ) + .map(function (idx, elem) { + return $(elem).val(); + }) + .get(); + + if (actions_type.length === 0) { + Hm_Notices.show("You must provide at least one action", "warning"); + return false; + } + + idx = 0; + actions_type.forEach(function (elem, key) { + if (actions_value[idx] === "" && actions_field_type[idx] !== "hidden") { + let order = ordinal_number(key + 1); + Hm_Notices.show( + "The " + order + " action (" + elem + ") must be provided", + "warning" + ); + validation_failed = true; + } + actions_parsed.push({ + action: elem, + value: actions_value[idx], + extra_option: actions_type[idx].extra_option, + extra_option_value: actions_extra_value[idx], + }); + idx++; + }); + + if ($("#stop_filtering").is(":checked")) { + actions_parsed.push({ + action: "stop", + value: "", + extra_option: "", + extra_option_value: "", + }); + } + + if ($(".modal_sieve_filter_name").val() == "") { + Hm_Notices.show("Filter name is required", "danger"); + return false; + } + + if (validation_failed) { + return false; + } + + Hm_Ajax.request( + [ + { name: "hm_ajax_hook", value: "ajax_sieve_save_filter" }, + { name: "imap_account", value: imap_account }, + { + name: "sieve_filter_name", + value: $(".modal_sieve_filter_name").val(), + }, + { + name: "sieve_filter_priority", + value: $(".modal_sieve_filter_priority").val(), + }, + { name: "is_editing_filter", value: is_editing_filter }, + { + name: "current_editing_filter_name", + value: current_editing_filter_name, + }, + { name: "conditions_json", value: JSON.stringify(conditions_parsed) }, + { name: "actions_json", value: JSON.stringify(actions_parsed) }, + { + name: "filter_test_type", + value: $(".modal_sieve_filter_test").val(), + }, + { name: "gen_script", value: gen_script }, + ], + function (res) { + if (Object.keys(res.script_details).length === 0) { + window.location.href = "?page=sieve_filters"; + } else { + edit_script_modal.open(); + $(".modal_sieve_script_textarea").val(res.script_details.gen_script); + $(".modal_sieve_script_name").val(res.script_details.filter_name); + $(".modal_sieve_script_priority").val( + res.script_details.filter_priority + ); + } + } + ); + + return true; + }; + + my.save_script = function (imap_account) { + if ($(".modal_sieve_script_name").val() === "") { + Hm_Notices.show("You must provide a name for your script", "warning"); + return false; + } + if ($(".modal_sieve_script_textarea").val() === "") { + Hm_Notices.show("Empty script", "warning"); + return false; + } + Hm_Ajax.request( + [ + { name: "hm_ajax_hook", value: "ajax_sieve_save_script" }, + { name: "imap_account", value: imap_account }, + { + name: "sieve_script_name", + value: $(".modal_sieve_script_name").val(), + }, + { + name: "sieve_script_priority", + value: $(".modal_sieve_script_priority").val(), + }, + { name: "is_editing_script", value: is_editing_script }, + { name: "current_editing_script", value: current_editing_script_name }, + { name: "script", value: $(".modal_sieve_script_textarea").val() }, + ], + function (res) { + window.location = window.location; + } + ); + }; + + my.add_filter_condition = function () { + let header_fields = ""; + let message_fields = ""; + + hm_sieve_condition_fields().Message.forEach(function (value) { + if (value.selected === true) { + message_fields += + '"; + } else { + message_fields += + '"; + } + }); + + hm_sieve_condition_fields().Header.forEach(function (value) { + if (value.selected === true) { + header_fields += + '"; + } else { + header_fields += + '"; + } + }); + + const extra_options = ` + + + + `; + + $(".sieve_list_conditions_modal").append(` + + + + + ${extra_options} + + + + + + + + + Delete + + + `); + }; + + my.add_filter_action = function (default_value = "") { + let possible_actions_html = ""; + + hm_sieve_possible_actions().forEach(function (value) { + if (value.selected === true) { + possible_actions_html += + '"; + return; + } + possible_actions_html += + '"; + }); + + const extra_options = ` + + + + `; + + $(".filter_actions_modal_table").append(` + + + + + ${extra_options} + + + + + Delete + + + `); + }; + + return my; +})({}); + + const add_filter_condition = Hm_Filters.add_filter_condition; + const add_filter_action = Hm_Filters.add_filter_action; + + +/************************************************************************************** +* MODAL EVENTS +**************************************************************************************/ +var hm_sieve_button_events = function (edit_filter_modal, edit_script_modal) { + $(document) + .off("click.sieve_toggle") + .on("click.sieve_toggle", ".sievefilters_accounts_title", function () { + $(this).parent().find(".sievefilters_accounts").toggleClass("d-none"); + }); + + $(document).on("click", ".add_filter", function () { + edit_filter_modal.setTitle("Add Filter"); + $(".modal_sieve_filter_priority").val(""); + $(".modal_sieve_filter_test").val("ALLOF"); + $("#stop_filtering").prop("checked", false); + hm_sieve_current_account = $(this).attr("account");; + edit_filter_modal.open(); + + // Reset the form fields when opening the modal + $(".modal_sieve_filter_name").val(""); + $(".modal_sieve_script_priority").val(""); + $(".sieve_list_conditions_modal").empty(); + $(".filter_actions_modal_table").empty(); + }); + $(document).on("click", ".add_script", function () { + edit_script_modal?.setTitle("Add Script"); + $(".modal_sieve_script_textarea").val(""); + $(".modal_sieve_script_name").val(""); + $(".modal_sieve_script_priority").val(""); + is_editing_script = false; + current_editing_script_name = ""; + hm_sieve_current_account = $(this).attr("account"); + edit_script_modal?.open(); + }); + + /** + * Delete action Button + */ + $(document).on("click", ".delete_else_action_modal_button", function (e) { + e.preventDefault(); + $(this).closest("tr").remove(); + }); + + /** + * Delete action Button + */ + $(document).on("click", ".delete_action_modal_button", function (e) { + e.preventDefault(); + $(this).closest("tr").remove(); + }); + + /** + * Delete Condition Button + */ + $(document).on("click", ".delete_condition_modal_button", function (e) { + e.preventDefault(); + $(this).closest("tr").remove(); + }); + + /** + * Add Condition Button + */ + $(document).on("click", ".sieve_add_condition_modal_button", function () { + add_filter_condition(); + }); + + /** + * Add Action Button + */ + $(document).on("click", ".filter_modal_add_action_btn", function () { + add_filter_action(); + }); + + /** + * Add Else Action Button + */ + $(document).on("click", ".filter_modal_add_else_action_btn", function () { + let possible_actions_html = ""; + + hm_sieve_possible_actions().forEach(function (value) { + if (value.selected === true) { + possible_actions_html += + '"; + return; + } + possible_actions_html += + '"; + }); + + $(".filter_else_actions_modal_table").append( + '' + + ' ' + + ' " + + " " + + " " + + " " + + ' ' + + ' Delete' + + " " + + "" + ); + }); + + /** + * Action change + */ + $(document).on("change", ".sieve_actions_select", function () { + let tr_elem = $(this).parent().parent(); + console.log(tr_elem.attr("default_value")); + let elem = $(this).parent().next().next(); + let elem_extra = $(this) + .parent() + .next() + .find(".condition_extra_action_value"); + let action_name = $(this).val(); + let selected_action; + hm_sieve_possible_actions().forEach(function (action) { + if (action_name === action.name) { + selected_action = action; + } + }); + if (selected_action) { + elem_extra.attr("type", "hidden"); + if (selected_action.extra_field) { + elem_extra.attr("type", "text"); + elem_extra.attr("placeholder", selected_action.extra_field_placeholder); + } + if (selected_action.type === "none") { + elem.html( + '' + ); + } + if (selected_action.type === "string") { + elem.html( + '' + ); + } + if (selected_action.type === "int") { + elem.html( + '' + ); + } + if (selected_action.type === "number") { + elem.html( + '' + ); + } + if (selected_action.type === "text") { + elem.html( + '' + ); + } + if (selected_action.type === "select") { + options = ""; + selected_action.values.forEach(function (val) { + if (tr_elem.attr("default_value") === val) { + options = + options + + '"; + } else { + options = + options + '"; + } + }); + elem.html( + '" + ); + } + if (selected_action.type === "mailbox") { + let mailboxes = null; + tr_elem.children().eq(2).html(hm_spinner()); + Hm_Ajax.request( + [ + { name: "hm_ajax_hook", value: "ajax_sieve_get_mailboxes" }, + { name: "imap_account", value: hm_sieve_current_account }, + ], + function (res) { + mailboxes = JSON.parse(res.mailboxes); + options = ""; + mailboxes.forEach(function (val) { + if (tr_elem.attr("default_value") === val) { + options = + options + + '"; + } else { + options = + options + '"; + } + }); + elem.html( + '" + ); + $("[name^=sieve_selected_action_value]") + .last() + .val(elem.parent().attr("default_value")); + } + ); + } + } + }); + + /** + * Condition type change + */ + $(document).on("change", ".add_condition_sieve_filters", function () { + let condition_name = $(this).val(); + let elem = $(this).parent().next().next().find(".condition_options"); + let elem_extra = $(this).parent().next().find(".condition_extra_value"); + let elem_type = $(this).parent().next().next().next(); + let condition; + let options_html = ""; + let input_type_html = ""; + hm_sieve_condition_fields().Message.forEach(function (cond) { + if (condition_name === cond.name) { + condition = cond; + } + }); + hm_sieve_condition_fields().Header.forEach(function (cond) { + if (condition_name === cond.name) { + condition = cond; + } + }); + if (condition) { + if (condition.extra_option === true) { + elem_extra.attr("type", "text"); + elem_extra.attr("placeholder", condition.extra_option_description); + } else { + elem_extra.attr("type", "hidden"); + } + condition.options.forEach(function (option) { + options_html += + '"; + options_html += + '"; + }); + elem.html(options_html); + + if (condition.type === "string") { + elem_type.html( + '' + ); + } + if (condition.type === "int") { + elem_type.html( + '' + ); + } + if (condition.type === "none") { + elem_type.html( + '' + ); + } + } + }); + + /** + * Delete filter event + */ + $(document).on("click", ".delete_filter", function (e) { + e.preventDefault(); + if (!confirm("Do you want to delete filter?")) { + return; + } + let obj = $(this); + Hm_Ajax.request( + [ + { name: "hm_ajax_hook", value: "ajax_sieve_delete_filter" }, + { name: "imap_account", value: $(this).attr("imap_account") }, + { name: "sieve_script_name", value: $(this).attr("script_name") }, + ], + function (res) { + if (res.script_removed == "1") { + obj.parent().parent().remove(); + } + } + ); + }); + + /** + * Toggle Filter + */ + $(".toggle_filter").on("change", function () { + const checkbox = $(this); + Hm_Ajax.request( + [ + { name: "hm_ajax_hook", value: "ajax_sieve_toggle_script_state" }, + { name: "imap_account", value: checkbox.attr("imap_account") }, + { name: "script_state", value: checkbox.prop("checked") }, + { name: "sieve_script_name", value: checkbox.attr("script_name") }, + ], + function (res) { + if (res.success) { + checkbox.prop("checked", !checkbox.prop("checked")); + } + } + ); + }); + + /** + * Delete script event + */ + $(document).on("click", ".delete_script", function (e) { + e.preventDefault(); + if (!confirm("Do you want to delete script?")) { + return; + } + let obj = $(this); + Hm_Ajax.request( + [ + { name: "hm_ajax_hook", value: "ajax_sieve_delete_script" }, + { name: "imap_account", value: $(this).attr("imap_account") }, + { name: "sieve_script_name", value: $(this).attr("script_name") }, + ], + function (res) { + if (res.script_removed == "1") { + obj.parent().parent().remove(); + } + } + ); + }); + + /** + * Edit script event + */ + $(document).on("click", ".edit_script", function (e) { + e.preventDefault(); + let obj = $(this); + edit_script_modal?.setTitle("Edit Script"); + hm_sieve_current_account = $(this).attr("account"); + is_editing_script = true; + current_editing_script_name = $(this).attr("script_name"); + hm_sieve_current_account = $(this).attr("imap_account"); + $(".modal_sieve_script_name").val($(this).attr("script_name_parsed")); + $(".modal_sieve_script_priority").val($(this).attr("priority")); + Hm_Ajax.request( + [ + { name: "hm_ajax_hook", value: "ajax_sieve_edit_script" }, + { name: "imap_account", value: $(this).attr("imap_account") }, + { name: "sieve_script_name", value: $(this).attr("script_name") }, + ], + function (res) { + $(".modal_sieve_script_textarea").html(res.script); + edit_script_modal?.open(); + } + ); + }); + + /** + * Edit filter event + */ + $(document).on("click", ".edit_filter", function (e) { + e.preventDefault(); + let obj = $(this); + hm_sieve_current_account = $(this).attr("account"); + is_editing_filter = true; + current_editing_filter_name = $(this).attr("script_name"); + hm_sieve_current_account = $(this).attr("imap_account"); + // $('#stop_filtering').prop('checked', false); + $(".modal_sieve_filter_name").val($(this).attr("script_name_parsed")); + $(".modal_sieve_filter_priority").val($(this).attr("priority")); + $(".sieve_list_conditions_modal").html(""); + $(".filter_actions_modal_table").html(""); + Hm_Ajax.request( + [ + { name: "hm_ajax_hook", value: "ajax_sieve_edit_filter" }, + { name: "imap_account", value: $(this).attr("imap_account") }, + { name: "sieve_script_name", value: $(this).attr("script_name") }, + ], + function (res) { + conditions = JSON.parse(JSON.parse(res.conditions)); + actions = JSON.parse(JSON.parse(res.actions)); + test_type = res.test_type; + $(".modal_sieve_filter_test").val(test_type); + conditions.forEach(function (condition) { + add_filter_condition(); + $(".add_condition_sieve_filters").last().val(condition.condition); + $(".add_condition_sieve_filters").last().trigger("change"); + $(".condition_options").last().val(condition.type); + $("[name^=sieve_selected_extra_option_value]") + .last() + .val(condition.extra_option_value); + if ($("[name^=sieve_selected_option_value]").last().is("input")) { + $("[name^=sieve_selected_option_value]") + .last() + .val(condition.value); + } + }); + + actions.forEach(function (action) { + if (action.action === "stop") { + $("#stop_filtering").prop("checked", true); + } else { + add_filter_action(action.value); + $(".sieve_actions_select").last().val(action.action); + $(".sieve_actions_select").last().trigger("change"); + $("[name^=sieve_selected_extra_action_value]") + .last() + .val(action.extra_option_value); + if ($("[name^=sieve_selected_action_value]").last().is("input")) { + $("[name^=sieve_selected_action_value]").last().val(action.value); + } else if ( + $("[name^=sieve_selected_action_value]").last().is("textarea") + ) { + $("[name^=sieve_selected_action_value]") + .last() + .text(action.value); + } + } + }); + edit_filter_modal.setTitle(current_editing_filter_name); + edit_filter_modal.open(); + } + ); + }); + return true; +}; + function blockListPageHandlers() { $(document).on('change', '.select_default_behaviour', function(e) { if ($(this).val() != 'Reject') { @@ -330,14 +1126,14 @@ function cleanUpSieveFiltersPage() { } function sieveFiltersPageHandler() { - let is_editing_script = false; - let current_editing_script_name = ''; - let is_editing_filter = false; - let current_editing_filter_name = ''; - let current_account; + + /************************************************************************************** * BOOTSTRAP SCRIPT MODAL **************************************************************************************/ + const save_filter = Hm_Filters.save_filter; + const save_script = Hm_Filters.save_script; + var edit_script_modal = new Hm_Modal({ size: 'xl', modalId: 'myEditScript' @@ -349,7 +1145,8 @@ function sieveFiltersPageHandler() { // add a button edit_script_modal.addFooterBtn('Save', 'btn-primary', async function () { - save_script(current_account); + console.log("Current account:", hm_sieve_current_account); + save_script(hm_sieve_current_account); }); @@ -361,13 +1158,15 @@ function sieveFiltersPageHandler() { modalId: 'myEditFilterModal', }); + hm_sieve_button_events(edit_filter_modal, edit_script_modal); + // set content edit_filter_modal.setContent(document.querySelector('#edit_filter_modal').innerHTML); $('#edit_filter_modal').remove(); // add a button edit_filter_modal.addFooterBtn('Save', 'btn-primary ms-auto', async function () { - let result = save_filter(current_account); + let result = save_filter(hm_sieve_current_account); if (result) { edit_filter_modal.hide(); } @@ -375,635 +1174,12 @@ function sieveFiltersPageHandler() { // add another button edit_filter_modal.addFooterBtn('Convert to code', 'btn-warning', async function () { - let result = save_filter(current_account, true); + let result = save_filter(hm_sieve_current_account, true); if (result) { edit_filter_modal.hide(); } }); - - function ordinal_number(n) - { - let ord = 'th'; - - if (n % 10 == 1 && n % 100 != 11) { - ord = 'st'; - } else if (n % 10 == 2 && n % 100 != 12) { - ord = 'nd'; - } else if (n % 10 == 3 && n % 100 != 13) { - ord = 'rd'; - } - - return n + ord; - } - - /************************************************************************************** - * FUNCTIONS - **************************************************************************************/ - function save_filter(imap_account, gen_script = false) { - let validation_failed = false - let conditions_parsed = [] - let actions_parsed = [] - let conditions = $('select[name^=sieve_selected_conditions_field]').map(function(idx, elem) { - return $(elem).val(); - }).get(); - - let conditions_type = $('select[name^=sieve_selected_conditions_options]').map(function(idx, elem) { - return $(elem).val(); - }).get(); - - let conditions_value = $('input[name^=sieve_selected_option_value]').map(function(idx, elem) { - return $(elem).val(); - }).get(); - - let conditions_extra_value = $('input[name^=sieve_selected_extra_option_value]').map(function(idx, elem) { - return $(elem).val(); - }).get(); - - let idx = 0; - if (conditions.length === 0) { - Hm_Notices.show('You must provide at least one condition', 'warning'); - return false; - } - - conditions.forEach(function (elem, key) { - if (conditions_value[idx] === "" && conditions_value[idx] !== 'none') { - let order = ordinal_number(key + 1); - let previous_messages = $('.sys_messages').html(); - previous_messages += previous_messages ? '
': ''; - Hm_Notices.show('The ' + order + ' condition (' + elem + ') must be provided', 'warning'); - validation_failed = true; - } - conditions_parsed.push( - { - 'condition': elem, - 'type': conditions_type[idx], - 'extra_option': conditions[idx].extra_option, - 'extra_option_value': conditions_extra_value[idx], - 'value': conditions_value[idx] - } - ) - idx = idx + 1; - }); - - let actions_type = $('select[name^=sieve_selected_actions]').map(function(idx, elem) { - return $(elem).val(); - }).get(); - let actions_value = $('[name^=sieve_selected_action_value]').map(function(idx, elem) { - return $(elem).val(); - }).get(); - let actions_field_type = $('[name^=sieve_selected_action_value]').map(function(idx, elem) { - return $(elem).attr('type'); - }).get(); - let actions_extra_value = $('input[name^=sieve_selected_extra_action_value]').map(function(idx, elem) { - return $(elem).val(); - }).get(); - - if (actions_type.length === 0) { - Hm_Notices.show('You must provide at least one action', 'warning'); - return false; - } - - idx = 0; - actions_type.forEach(function (elem, key) { - console.log(actions_field_type[idx]) - if (actions_value[idx] === "" && actions_field_type[idx] !== 'hidden') { - let order = ordinal_number(key + 1); - let previous_messages = $('.sys_messages').html(); - previous_messages += previous_messages ? '
': ''; - Hm_Notices.show('The ' + order + ' action (' + elem + ') must be provided', 'waring'); - validation_failed = true; - } - actions_parsed.push( - { - 'action': elem, - 'value': actions_value[idx], - 'extra_option': actions_type[idx].extra_option, - 'extra_option_value': actions_extra_value[idx], - } - ) - idx = idx + 1; - }); - - if ($('#stop_filtering').is(':checked')) { - actions_parsed.push( - { - 'action': "stop", - 'value': "", - 'extra_option': "", - 'extra_option_value': "", - } - ) - } - if ($('.modal_sieve_filter_name').val() == "") { - Hm_Notices.show('Filter name is required', 'danger'); - return false; - } - - if (validation_failed) { - return false; - } - - Hm_Ajax.request( - [ {'name': 'hm_ajax_hook', 'value': 'ajax_sieve_save_filter'}, - {'name': 'imap_account', 'value': imap_account}, - {'name': 'sieve_filter_name', 'value': $('.modal_sieve_filter_name').val()}, - {'name': 'sieve_filter_priority', 'value': $('.modal_sieve_filter_priority').val()}, - {'name': 'is_editing_filter', 'value': is_editing_filter}, - {'name': 'current_editing_filter_name', 'value': current_editing_filter_name}, - {'name': 'conditions_json', 'value': JSON.stringify(conditions_parsed)}, - {'name': 'actions_json', 'value': JSON.stringify(actions_parsed)}, - {'name': 'filter_test_type', 'value': $('.modal_sieve_filter_test').val()}, - {'name': 'gen_script', 'value': gen_script}, - ], - function(res) { - if (Object.keys(res.script_details).length === 0) { - window.location = window.location; - } else { - edit_script_modal.open(); - $('.modal_sieve_script_textarea').val(res.script_details.gen_script); - $('.modal_sieve_script_name').val(res.script_details.filter_name); - $('.modal_sieve_script_priority').val(res.script_details.filter_priority); - } - } - ); - - return true; - } - - function save_script(imap_account) { - if ($('.modal_sieve_script_name').val() === "") { - Hm_Notices.show('You must provide a name for your script', 'warning'); - return false; - } - if ($('.modal_sieve_script_textarea').val() === "") { - Hm_Notices.show('Empty script', 'warning'); - return false; - } - Hm_Ajax.request( - [ {'name': 'hm_ajax_hook', 'value': 'ajax_sieve_save_script'}, - {'name': 'imap_account', 'value': imap_account}, - {'name': 'sieve_script_name', 'value': $('.modal_sieve_script_name').val()}, - {'name': 'sieve_script_priority', 'value': $('.modal_sieve_script_priority').val()}, - {'name': 'is_editing_script', 'value': is_editing_script}, - {'name': 'current_editing_script', 'value': current_editing_script_name}, - {'name': 'script', 'value': $('.modal_sieve_script_textarea').val()}], - function(res) { - window.location = window.location; - } - ); - } - - /************************************************************************************** - * MODAL EVENTS - **************************************************************************************/ - $(document).off('click').on('click', '.sievefilters_accounts_title', function() { - $(this).parent().find('.sievefilters_accounts').toggleClass('d-none'); - }); - - $(document).on('click', '.add_filter', function() { - edit_filter_modal.setTitle('Add Filter'); - $('.modal_sieve_filter_priority').val(''); - $('.modal_sieve_filter_test').val('ALLOF'); - $('#stop_filtering').prop('checked', false); - current_account = $(this).attr('account'); - edit_filter_modal.open(); - - // Reset the form fields when opening the modal - $(".modal_sieve_filter_name").val(''); - $(".modal_sieve_script_priority").val(''); - $(".sieve_list_conditions_modal").empty(); - $(".filter_actions_modal_table").empty(); - }); - $(document).on('click', '.add_script', function() { - edit_script_modal.setTitle('Add Script'); - $('.modal_sieve_script_textarea').val(''); - $('.modal_sieve_script_name').val(''); - $('.modal_sieve_script_priority').val(''); - is_editing_script = false; - current_editing_script_name = ''; - current_account = $(this).attr('account'); - edit_script_modal.open(); - }); - - /** - * Delete action Button - */ - $(document).on('click', '.delete_else_action_modal_button', function (e) { - e.preventDefault(); - $(this).parent().parent().remove(); - }); - - /** - * Delete action Button - */ - $(document).on('click', '.delete_action_modal_button', function (e) { - e.preventDefault(); - $(this).parent().parent().remove(); - }); - - /** - * Delete Condition Button - */ - $(document).on('click', '.delete_condition_modal_button', function (e) { - e.preventDefault(); - $(this).parent().parent().remove(); - }); - - function add_filter_condition() { - let header_fields = ''; - let message_fields = ''; - - hm_sieve_condition_fields().Message.forEach(function (value) { - if (value.selected === true) { - message_fields += ''; - } else { - message_fields += ''; - } - }); - hm_sieve_condition_fields().Header.forEach(function (value) { - if (value.selected === true) { - header_fields += ''; - } else { - header_fields += ''; - } - }); - let extra_options = ''; - $('.sieve_list_conditions_modal').append( - ' ' + - ' ' + - ' ' + - ' ' + - extra_options + - ' ' + - ' ' + - ' ' + - ' ' + - ' ' + - ' ' + - ' ' + - ' Delete' + - ' ' + - ' ' - ); - } - - /** - * Add Condition Button - */ - $(document).on('click', '.sieve_add_condition_modal_button', function () { - add_filter_condition(); - }); - - function add_filter_action(default_value = '') { - let possible_actions_html = ''; - - hm_sieve_possible_actions().forEach(function (value) { - if (value.selected === true) { - possible_actions_html += ''; - return; - } - possible_actions_html += ''; - }); - let extra_options = ''; - $('.filter_actions_modal_table').append( - '' + - ' ' + - ' ' + - ' ' + - extra_options + - ' ' + - ' ' + - ' ' + - ' ' + - ' Delete' + - ' ' + - '' - ); - } - - /** - * Add Action Button - */ - $(document).on('click', '.filter_modal_add_action_btn', function () { - add_filter_action(); - }); - - /** - * Add Else Action Button - */ - $(document).on('click', '.filter_modal_add_else_action_btn', function () { - let possible_actions_html = ''; - - hm_sieve_possible_actions().forEach(function (value) { - if (value.selected === true) { - possible_actions_html += ''; - return; - } - possible_actions_html += ''; - }); - - $('.filter_else_actions_modal_table').append( - '' + - ' ' + - ' ' + - ' ' + - ' ' + - ' ' + - ' ' + - ' Delete' + - ' ' + - '' - ); - }); - - - /** - * Action change - */ - $(document).on('change', '.sieve_actions_select', function () { - let tr_elem = $(this).parent().parent(); - console.log(tr_elem.attr('default_value')); - let elem = $(this).parent().next().next(); - let elem_extra = $(this).parent().next().find('.condition_extra_action_value'); - let action_name = $(this).val(); - let selected_action; - hm_sieve_possible_actions().forEach(function (action) { - if (action_name === action.name) { - selected_action = action; - } - }); - if (selected_action) { - elem_extra.attr('type', 'hidden'); - if (selected_action.extra_field) { - elem_extra.attr('type', 'text'); - elem_extra.attr('placeholder', selected_action.extra_field_placeholder) - } - if (selected_action.type === 'none') { - elem.html(''); - } - if (selected_action.type === 'string') { - elem.html(''); - } - if (selected_action.type === 'int') { - elem.html(''); - } - if (selected_action.type === 'number') { - elem.html(''); - } - if (selected_action.type === 'text') { - elem.html(''); - } - if (selected_action.type === 'select') { - options = ''; - selected_action.values.forEach(function(val) { - if (tr_elem.attr('default_value') === val) { - options = options + '' - } else { - options = options + '' - } - }); - elem.html(''); - } - if (selected_action.type === 'mailbox') { - let mailboxes = null; - tr_elem.children().eq(2).html(hm_spinner()); - Hm_Ajax.request( - [ {'name': 'hm_ajax_hook', 'value': 'ajax_sieve_get_mailboxes'}, - {'name': 'imap_account', 'value': current_account} ], - function(res) { - mailboxes = JSON.parse(res.mailboxes); - options = ''; - mailboxes.forEach(function(val) { - if (tr_elem.attr('default_value') === val) { - options = options + '' - } else { - options = options + '' - } - }); - elem.html(''); - $("[name^=sieve_selected_action_value]").last().val(elem.parent().attr('default_value')); - } - ); - } - } - }) - - /** - * Condition type change - */ - $(document).on('change', '.add_condition_sieve_filters', function () { - let condition_name = $(this).val(); - let elem = $(this).parent().next().next().find('.condition_options'); - let elem_extra = $(this).parent().next().find('.condition_extra_value'); - let elem_type = $(this).parent().next().next().next(); - let condition; - let options_html = ''; - let input_type_html = ''; - hm_sieve_condition_fields().Message.forEach(function (cond) { - if (condition_name === cond.name) { - condition = cond; - } - }); - hm_sieve_condition_fields().Header.forEach(function (cond) { - if (condition_name === cond.name) { - condition = cond; - } - }); - if (condition) { - if (condition.extra_option === true) { - elem_extra.attr('type', 'text'); - elem_extra.attr('placeholder', condition.extra_option_description); - } else { - elem_extra.attr('type', 'hidden'); - } - condition.options.forEach(function (option) { - options_html += ''; - options_html += ''; - }); - elem.html(options_html); - - if (condition.type === 'string') { - elem_type.html('') - } - if (condition.type === 'int') { - elem_type.html('') - } - if (condition.type === 'none') { - elem_type.html('') - } - } - }); - - /** - * Delete filter event - */ - $(document).on('click', '.delete_filter', function (e) { - e.preventDefault(); - if (!confirm('Do you want to delete filter?')) { - return; - } - let obj = $(this); - Hm_Ajax.request( - [ {'name': 'hm_ajax_hook', 'value': 'ajax_sieve_delete_filter'}, - {'name': 'imap_account', 'value': $(this).attr('imap_account')}, - {'name': 'sieve_script_name', 'value': $(this).attr('script_name')}], - function(res) { - if (res.script_removed == '1') { - obj.parent().parent().remove(); - } - } - ); - }); - - /** - * Toggle Filter - */ - $('.toggle_filter').on('change', function () { - const checkbox = $(this); - Hm_Ajax.request( - [ {'name': 'hm_ajax_hook', 'value': 'ajax_sieve_toggle_script_state'}, - {'name': 'imap_account', 'value': checkbox.attr('imap_account')}, - {'name': 'script_state', 'value': checkbox.prop('checked')}, - {'name': 'sieve_script_name', 'value': checkbox.attr('script_name')}], - function(res) { - if (res.success) { - checkbox.prop('checked', !checkbox.prop('checked')); - } - } - ); - }); - - /** - * Delete script event - */ - $(document).on('click', '.delete_script', function (e) { - e.preventDefault(); - if (!confirm('Do you want to delete script?')) { - return; - } - let obj = $(this); - Hm_Ajax.request( - [ {'name': 'hm_ajax_hook', 'value': 'ajax_sieve_delete_script'}, - {'name': 'imap_account', 'value': $(this).attr('imap_account')}, - {'name': 'sieve_script_name', 'value': $(this).attr('script_name')}], - function(res) { - if (res.script_removed == '1') { - obj.parent().parent().remove(); - } - } - ); - }); - - /** - * Edit script event - */ - $(document).on('click', '.edit_script', function (e) { - e.preventDefault(); - let obj = $(this); - edit_script_modal.setTitle('Edit Script'); - current_account = $(this).attr('account'); - is_editing_script = true; - current_editing_script_name = $(this).attr('script_name'); - current_account = $(this).attr('imap_account'); - $('.modal_sieve_script_name').val($(this).attr('script_name_parsed')); - $('.modal_sieve_script_priority').val($(this).attr('priority')); - Hm_Ajax.request( - [ {'name': 'hm_ajax_hook', 'value': 'ajax_sieve_edit_script'}, - {'name': 'imap_account', 'value': $(this).attr('imap_account')}, - {'name': 'sieve_script_name', 'value': $(this).attr('script_name')}], - function(res) { - $('.modal_sieve_script_textarea').html(res.script); - edit_script_modal.open(); - } - ); - }); - - /** - * Edit filter event - */ - $(document).on('click', '.edit_filter', function (e) { - e.preventDefault(); - let obj = $(this); - current_account = $(this).attr('account'); - is_editing_filter = true; - current_editing_filter_name = $(this).attr('script_name'); - current_account = $(this).attr('imap_account'); - // $('#stop_filtering').prop('checked', false); - $('.modal_sieve_filter_name').val($(this).attr('script_name_parsed')); - $('.modal_sieve_filter_priority').val($(this).attr('priority')); - $('.sieve_list_conditions_modal').html(''); - $('.filter_actions_modal_table').html(''); - Hm_Ajax.request( - [ {'name': 'hm_ajax_hook', 'value': 'ajax_sieve_edit_filter'}, - {'name': 'imap_account', 'value': $(this).attr('imap_account')}, - {'name': 'sieve_script_name', 'value': $(this).attr('script_name')}], - function(res) { - conditions = JSON.parse(JSON.parse(res.conditions)); - actions = JSON.parse(JSON.parse(res.actions)); - test_type = res.test_type; - $(".modal_sieve_filter_test").val(test_type); - conditions.forEach(function (condition) { - add_filter_condition(); - $(".add_condition_sieve_filters").last().val(condition.condition); - $(".add_condition_sieve_filters").last().trigger('change'); - $(".condition_options").last().val(condition.type); - $("[name^=sieve_selected_extra_option_value]").last().val(condition.extra_option_value); - if ($("[name^=sieve_selected_option_value]").last().is('input')) { - $("[name^=sieve_selected_option_value]").last().val(condition.value); - } - }); - - actions.forEach(function (action) { - if (action.action === "stop") { - $('#stop_filtering').prop('checked', true); - } else { - add_filter_action(action.value); - $(".sieve_actions_select").last().val(action.action); - $(".sieve_actions_select").last().trigger('change'); - $("[name^=sieve_selected_extra_action_value]").last().val(action.extra_option_value); - if ($("[name^=sieve_selected_action_value]").last().is('input')) { - $("[name^=sieve_selected_action_value]").last().val(action.value); - } else if ($("[name^=sieve_selected_action_value]").last().is('textarea')) { - $("[name^=sieve_selected_action_value]").last().text(action.value); - } - } - }); - edit_filter_modal.setTitle(current_editing_filter_name); - edit_filter_modal.open(); - } - ); - }); load_sieve_filters('ajax_account_sieve_filters'); }