From: Shravan A Y Date: Mon, 10 Mar 2025 16:21:59 +0000 (+0530) Subject: [WebUI] Add file upload to Test Selectors (#5381) X-Git-Tag: 3.12.0~12^2~2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=44217892ae46724dcdb35bf96fe8552d58c3ab52;p=thirdparty%2Frspamd.git [WebUI] Add file upload to Test Selectors (#5381) Squashed and rebased original commits from ShravanAYG’s selector-file-upload branch Co-authored-by: ShravanAYG See: https://github.com/rspamd/rspamd/pull/5381 --- diff --git a/interface/css/rspamd.css b/interface/css/rspamd.css index 896f920088..a79fed28b0 100644 --- a/interface/css/rspamd.css +++ b/interface/css/rspamd.css @@ -418,13 +418,18 @@ table#symbolsTable input[type="number"] { .outline-dashed-primary { outline: 2px dashed var(--bs-primary); } -#scanMsgSource:placeholder-shown { +#scanMsgSource:placeholder-shown, +#selectorsMsgArea:placeholder-shown { background-image: url("../img/drop-area.svg"); background-repeat: no-repeat; background-position: center; opacity: 0.8; } -#scanMsgSource:not(:placeholder-shown) { background-image: none;} + +#scanMsgSource:not(:placeholder-shown), +#selectorsMsgArea:not(:placeholder-shown) { + background-image: none; +} .scorebar-spam { background-color: rgba(240 0 0 / 0.1) !important; diff --git a/interface/index.html b/interface/index.html index cf21876012..b176d65273 100644 --- a/interface/index.html +++ b/interface/index.html @@ -580,6 +580,10 @@
Test Rspamd selectors +
+ + +
@@ -608,7 +612,7 @@
- +
diff --git a/interface/js/app/common.js b/interface/js/app/common.js index ace4bbba17..20c13f9f91 100644 --- a/interface/js/app/common.js +++ b/interface/js/app/common.js @@ -261,5 +261,71 @@ define(["jquery", "nprogress"], ).appendTo(ftFilter.$dropdown); }; + ui.fileUtils = { + files: null, + filesIdx: 0, + + enableButton(button, textArea, validator) { + const hasText = $.trim($(textArea).val()).length > 0; + const needsValidation = validator !== "none"; + + $(button).prop("disabled", !hasText || (needsValidation && !$(validator).hasClass("is-valid"))); + }, + + readFile(callback, textArea, button, validator) { + if (!this.files || this.files.length === 0) { + alertMessage("alert-error", "No files selected."); + return; + } + + const reader = new FileReader(); + + reader.onload = () => { + $(textArea).val(reader.result).trigger("input"); + this.enableButton(button, textArea, validator); + + if (callback) callback(reader.result); + }; + reader.onerror = () => alertMessage("alert-error", "Error reading file."); + reader.readAsText(this.files[this.filesIdx]); + }, + + handleFileInput(fileSrc, textArea, button, fileInput, validator) { + ({ + files: this.files + } = fileSrc); + this.filesIdx = 0; + + if (!this.files.length) { + alertMessage("alert-warning", "No file was provided."); + return; + } + $(fileInput)[0].files = this.files; + // eslint-disable-next-line no-alert + if (this.files.length === 1 || confirm(`Are you sure you want to process ${this.files.length} files?`)) { + this.readFile(null, textArea, button, validator); + } + }, + + setupFileHandling(textArea, fileInput, button, validator) { + const highlightClass = "outline-dashed-primary bg-primary-subtle"; + + $(textArea) + .on("dragenter dragover", (e) => { + e.preventDefault(); + $(textArea).addClass(highlightClass); + }) + .on("dragleave drop", () => $(textArea).removeClass(highlightClass)) + .on("drop", (e) => { + e.preventDefault(); + this.handleFileInput(e.originalEvent.dataTransfer, textArea, button, fileInput, validator); + }); + $(fileInput).on("change", (e) => { + this.handleFileInput(e.target, textArea, button, fileInput, validator); + }); + $(textArea).on("input", () => this.enableButton(button, textArea, validator)); + } + }; + return ui; }); diff --git a/interface/js/app/selectors.js b/interface/js/app/selectors.js index c2b8b27e5e..788ceeacb6 100644 --- a/interface/js/app/selectors.js +++ b/interface/js/app/selectors.js @@ -135,6 +135,12 @@ define(["jquery", "app/common"], $("#selectorsSelArea").on("input", () => { checkSelectors(); }); + $("#selectorsMsgClean").on("click", () => { + $("#selectorsMsgArea").val(""); + $("#selectorsFile").val(""); + }); + + common.fileUtils.setupFileHandling("#selectorsMsgArea", "#selectorsFile", "#selectorsChkMsgBtn", "#selectorsSelArea"); return ui; }); diff --git a/interface/js/app/upload.js b/interface/js/app/upload.js index d5283cdb16..2ba4b61679 100644 --- a/interface/js/app/upload.js +++ b/interface/js/app/upload.js @@ -28,8 +28,8 @@ define(["jquery", "app/common", "app/libft"], ($, common, libft) => { "use strict"; const ui = {}; - let files = null; let filesIdx = null; + let files = null; let scanTextHeaders = {}; function uploadText(data, url, headers, method = "POST") { @@ -70,18 +70,14 @@ define(["jquery", "app/common", "app/libft"], .prop("disabled", (disable || $.trim($("textarea").val()).length === 0)); } - function setFileInputFiles(i) { + function updateFileInput(i) { const dt = new DataTransfer(); - if (arguments.length) dt.items.add(files[i]); + if (arguments.length > 0 && files && files[i]) { + dt.items.add(files[i]); + } $("#formFile").prop("files", dt.files); } - function readFile(callback, i) { - const reader = new FileReader(); - reader.readAsText(files[(arguments.length === 1) ? 0 : i]); - reader.onload = () => callback(reader.result); - } - function scanText(data) { enable_disable_scan_btn(true); common.query("checkv2", { @@ -109,13 +105,15 @@ define(["jquery", "app/common", "app/libft"], libft.initHistoryTable(data, items, "scan", libft.columns_v2("scan"), true, () => { if (files && filesIdx < files.length - 1) { - readFile((result) => { + common.fileUtils.files = files; + common.fileUtils.filesIdx = ++filesIdx; + common.fileUtils.readFile((result) => { if (filesIdx === files.length - 1) { $("#scanMsgSource").val(result); - setFileInputFiles(filesIdx); + updateFileInput(filesIdx); } scanText(result); - }, ++filesIdx); + }, "#scanMsgSource", "#scanCheckMsgBtn", "none"); } else { enable_disable_scan_btn(); $("#cleanScanHistory, #scan .ft-columns-dropdown .btn-dropdown-apply") @@ -148,6 +146,7 @@ define(["jquery", "app/common", "app/libft"], }); } + function getFuzzyHashes(data) { function fillHashTable(rules) { $("#hashTable tbody").empty(); @@ -187,7 +186,8 @@ define(["jquery", "app/common", "app/libft"], $("#cleanScanHistory").off("click"); $("#cleanScanHistory").on("click", (e) => { e.preventDefault(); - if (!confirm("Are you sure you want to clean scan history?")) { // eslint-disable-line no-alert + // eslint-disable-next-line no-alert + if (!confirm("Are you sure you want to clean scan history?")) { return; } libft.destroyTable("scan"); @@ -200,7 +200,7 @@ define(["jquery", "app/common", "app/libft"], enable_disable_scan_btn(); if (files) { files = null; - setFileInputFiles(); + updateFileInput(); } }); @@ -304,39 +304,7 @@ define(["jquery", "app/common", "app/libft"], }); - function fileInputHandler(obj) { - ({files} = obj); - filesIdx = 0; - - if (files.length === 1) { - setFileInputFiles(0); - enable_disable_scan_btn(); - readFile((result) => { - $("#scanMsgSource").val(result); - enable_disable_scan_btn(); - }); - // eslint-disable-next-line no-alert - } else if (files.length < 10 || confirm("Are you sure you want to scan " + files.length + " files?")) { - getScanTextHeaders(); - readFile((result) => scanText(result)); - } - } - - const dragoverClassList = "outline-dashed-primary bg-primary-subtle"; - $("#scanMsgSource") - .on("dragenter dragover dragleave drop", (e) => { - e.preventDefault(); - e.stopPropagation(); - }) - .on("dragenter dragover", () => { - $("#scanMsgSource").addClass(dragoverClassList); - }) - .on("dragleave drop", () => { - $("#scanMsgSource").removeClass(dragoverClassList); - }) - .on("drop", (e) => fileInputHandler(e.originalEvent.dataTransfer)); - - $("#formFile").on("change", (e) => fileInputHandler(e.target)); + common.fileUtils.setupFileHandling("#scanMsgSource", "#formFile", "#scanCheckMsgBtn", "none"); return ui; });