[Bps-public-commit] rt-extension-spamfilter branch add-checkbox-selection created. 229dc8741329e7caa183eff7d6be042adefe8f97

BPS Git Server git at git.bestpractical.com
Thu Jul 13 11:50:27 UTC 2023


This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "rt-extension-spamfilter".

The branch, add-checkbox-selection has been created
        at  229dc8741329e7caa183eff7d6be042adefe8f97 (commit)

- Log -----------------------------------------------------------------
commit 229dc8741329e7caa183eff7d6be042adefe8f97
Author: Ronaldo Richieri <ronaldo at bestpractical.com>
Date:   Fri Jul 7 16:49:44 2023 -0300

    Implement multiple selection of checkboxes holding shift key
    
    Improve the selection of large number of Tickets/Messages by holding
    shift key and clicking on the checkbox.

diff --git a/html/Tools/SpamFilter/List.html b/html/Tools/SpamFilter/List.html
index 44f714e..cc63207 100644
--- a/html/Tools/SpamFilter/List.html
+++ b/html/Tools/SpamFilter/List.html
@@ -98,6 +98,38 @@
                 }
             }
         });
+        // Enable shift selection of checkboxes
+        lastReleaseSelected = null;
+        lastDeleteSelected = null;
+        ReleaseCheckboxes = jQuery('input.not_spam');
+        DeleteCheckboxes = jQuery('input.discard');
+        jQuery('input.not_spam,input.discard').click( function (e) {
+                // get id and split it
+                var id = this.id.split('-');
+                if (id[0] == 'Release') {
+                    if (!lastReleaseSelected) {
+                        lastReleaseSelected = this;
+                        return;
+                    }
+                    if (e.shiftKey) {
+                        var start = ReleaseCheckboxes.index(this);
+                        var end = ReleaseCheckboxes.index(lastReleaseSelected);
+                        ReleaseCheckboxes.slice(Math.min(start,end), Math.max(start,end)+ 1).prop('checked', lastReleaseSelected.checked).change();
+                    }
+                    lastReleaseSelected = this;
+                } else {
+                    if (!lastDeleteSelected) {
+                        lastDeleteSelected = this;
+                        return;
+                    }
+                    if (e.shiftKey) {
+                        var start = DeleteCheckboxes.index(this);
+                        var end = DeleteCheckboxes.index(lastDeleteSelected);
+                        DeleteCheckboxes.slice(Math.min(start,end), Math.max(start,end)+ 1).prop('checked', lastDeleteSelected.checked).change();
+                    }
+                    lastDeleteSelected = this;
+                }
+        });
     });
 </script>
 

commit 6b14b8b836aa170b386fe3d1af3a691cd8ddbba1
Author: Ronaldo Richieri <ronaldo at bestpractical.com>
Date:   Thu Jul 13 08:48:37 2023 -0300

    Add option to configure rows per page in spam list

diff --git a/html/Tools/SpamFilter/List.html b/html/Tools/SpamFilter/List.html
index cdfa7c7..44f714e 100644
--- a/html/Tools/SpamFilter/List.html
+++ b/html/Tools/SpamFilter/List.html
@@ -163,7 +163,7 @@ unless ($Format) {
 $Order    ||= 'ASC';
 $OrderBy  ||= 'id';
 
-$Rows ||= $ARGS{RowsPerPage} || 50;
+$Rows ||= RT->Config->Get('SpamListRowsPerPage') || $ARGS{RowsPerPage} || 50;
 $Page = 1 unless $Page && $Page > 0;
 
 use RT::Spams;
diff --git a/lib/RT/Extension/SpamFilter.pm b/lib/RT/Extension/SpamFilter.pm
index 3b9b02c..d0cdec9 100644
--- a/lib/RT/Extension/SpamFilter.pm
+++ b/lib/RT/Extension/SpamFilter.pm
@@ -113,6 +113,8 @@ is shown below:
         }
     );
 
+    Set( $SpamListRowsPerPage, 50 );
+
 =head2 C<@SpamFilters>
 
 The C<@SpamFilters> array is an array of hashes.  Each hash
@@ -146,6 +148,11 @@ presence of the spam header and then add the score you configure.
 The C<$SpamFilterThreshold> is the score above which an incoming message
 is considered to be spam and placed in the spam list.
 
+=head2 C<$SpamListRowsPerPage>
+
+The C<$SpamListRowsPerPage> is an optional configuration to change the
+number of rows to display per page in the spam list. Default is 50.
+
 =head1 AUTHOR
 
 Best Practical Solutions, LLC E<lt>modules at bestpractical.comE<gt>

commit 849cca6ff8c864e0acc7105805996ac30e98c57e
Author: Ronaldo Richieri <ronaldo at bestpractical.com>
Date:   Fri Jul 7 16:26:05 2023 -0300

    Implement checkbox selection for spam filter actions
    
    It's now possible to select multiple spam filter actions and perform
    bulk actions on them.

diff --git a/html/Elements/RT__Spam/ColumnMap b/html/Elements/RT__Spam/ColumnMap
index 339867d..1541667 100644
--- a/html/Elements/RT__Spam/ColumnMap
+++ b/html/Elements/RT__Spam/ColumnMap
@@ -53,25 +53,6 @@ $Attr => undef
 
 <%once>
 
-# For readability, ncapsulate the button-generating code into a
-# function here rather than putting it inline in the big hash.
-my $buttons_sub = sub {
-    my ($email) = @_;
-
-    my $ret = '';
-    if ($email->Status ne 'resolved') {
-       $ret .= '<button type="button" class="create_user" name="Release-' . $email->id . '">' . loc('Not Spam') . '</button>';
-    }
-    if ($email->Status ne 'deleted') {
-        $ret .= ' <button type="button" class="discard" name="Delete-' . $email->id . '">' . loc('Delete') . '</button>';
-    }
-
-    # Here's a magical thing... if you return a *reference* to a scalar,
-    # the result is not HTML-escaped.  If you just return a scalar, it is.
-    # Hence the \ before $ret.
-    return \$ret;
-};
-
 my $COLUMN_MAP;
 
 $COLUMN_MAP = {
@@ -111,9 +92,49 @@ $COLUMN_MAP = {
         title     => 'Score', # loc
         value     => sub { return $_[0]->Score }
     },
-    Disposition => {
-        title     => 'Disposition', #loc
-        value     => $buttons_sub,
+    NotSpam => {
+        # Here's a magical thing... if you return a *reference* to a scalar,
+        # the result is not HTML-escaped.  If you just return a scalar, it is.
+        # Hence the \ before $ret.
+        title => sub {
+            return \qq{
+<div class="custom-control custom-checkbox">
+  <input type="checkbox" name="not_spam_all" id="not_spam_all" value="1" class="checkbox custom-control-input" />
+  <label class="custom-control-label" for="not_spam_all">Not Spam</label>
+</div>
+};
+        },
+        value => sub {
+            if ( $_[0]->Status ne 'resolved' ) {
+                return \(
+'<div class="custom-control custom-checkbox">
+  <input type="checkbox" name="Release" id="Release-'.$_[0]->id.'" value="'.$_[0]->id.'" class="not_spam checkbox custom-control-input" />
+  <label class="custom-control-label" for="Release-'.$_[0]->id.'"></label>
+</div>');
+            }
+        },
+    },
+    Delete => {
+        # Here's a magical thing... if you return a *reference* to a scalar,
+        # the result is not HTML-escaped.  If you just return a scalar, it is.
+        # Hence the \ before $ret.
+        title => sub {
+            return \qq{
+<div class="custom-control custom-checkbox">
+  <input type="checkbox" name="discard_all" id="discard_all" value="1" class="checkbox custom-control-input" />
+  <label class="custom-control-label" for="discard_all">Delete</label>
+</div>
+};
+        },
+        value => sub {
+            if ( $_[0]->Status ne 'deleted' ) {
+                return \(
+'<div class="custom-control custom-checkbox">
+  <input type="checkbox" name="Delete" id="Delete-'.$_[0]->id.'" value="'.$_[0]->id.'" class="discard checkbox custom-control-input" />
+  <label class="custom-control-label" for="Delete-'.$_[0]->id.'"></label>
+</div>');
+            }
+        },
     },
 };
 
diff --git a/html/Tools/SpamFilter/List.html b/html/Tools/SpamFilter/List.html
index f5a969e..cdfa7c7 100644
--- a/html/Tools/SpamFilter/List.html
+++ b/html/Tools/SpamFilter/List.html
@@ -48,19 +48,55 @@
 <& /Elements/Header, Title => $title &>
 <& /Elements/Tabs &>
 
+<style type="text/css">
+    /* allow multiple checkboxes to be checked holding shift key*/
+    .checkbox {
+        z-index: 1;
+    }
+    .custom-checkbox label {
+        white-space: nowrap;
+    }
+</style>
 <script type="text/javascript">
     jQuery( function() {
-        jQuery('button.create_user').click( function () {
-            url = new URL(window.location.href);
-            status = url.searchParams.get('Status') || 'new';
-            bits = this.name.split('-');
-            window.location.href = '?emailid=' + bits[1] + '&Action=' + bits[0] + '&Status=' + status;
+        // adjust the width of the checkboxes columns since it's not possible
+        // to add specific class to the th element
+        jQuery('#discard_all,#not_spam_all').closest('th').css('width', '1%');
+
+        jQuery('#not_spam_all').change( function () {
+            // toggle all checkboxes
+            jQuery('input.not_spam').prop('checked', this.checked).change();
+            jQuery('#discard_all').prop('checked', false);
         });
-        jQuery('button.discard').click( function () {
-            url = new URL(window.location.href);
-            status = url.searchParams.get('Status') || 'new';
-            bits = this.name.split('-');
-            window.location.href = '?emailid=' + bits[1] + '&Action=' + bits[0] + '&Status=' + status;
+        jQuery('#discard_all').change( function () {
+            // toggle all checkboxes
+            jQuery('input.discard').prop('checked', this.checked).change();
+            jQuery('#not_spam_all').prop('checked', false);
+        });
+        // check if the corresponding Release-X or Delete-X is already checked
+        // and uncheck it
+        jQuery('input.not_spam,input.discard').change( function () {
+            // get id and split it
+            var id = this.id.split('-');
+
+            if (!this.checked) {
+                // disable the oposite checkbox
+                if (id[0] == 'Release') {
+                    jQuery('#not_spam_all').prop('checked', false);
+                } else {
+                    jQuery('#discard_all').prop('checked', false);
+                }
+                return;
+            } else {
+                // disable the oposite checkbox
+                if (id[0] == 'Release') {
+                    jQuery('#Delete-' + id[1]).prop('checked', false);
+                    jQuery('#discard_all').prop('checked', false);
+                } else {
+                    jQuery('#Release-' + id[1]).prop('checked', false);
+                    jQuery('#not_spam_all').prop('checked', false);
+                }
+            }
         });
     });
 </script>
@@ -68,6 +104,7 @@
 <& /Elements/ListActions, actions => \@results &>
 
 <div class="spams">
+<form method="post" enctype="multipart/form-data" name="SpamUpdate" id="SpamUpdate">
 <& /Elements/CollectionList, 
     Collection => $emails,
     AllowSorting => 1,
@@ -82,10 +119,46 @@
    &>
 </div>
 
+<hr />
+
+<div class="form-row">
+  <div class="col-12">
+    <& /Elements/Submit, Label => loc('Update') &>
+  </div>
+</div>
+
+</form>
+
 <%init>
 
 my @results;
-$Format ||= qq{'<a href="__WebPath__/Tools/SpamFilter/Display.html?id=__id__">__id__</a>/TITLE:#','<a href="__WebPath__/Tools/SpamFilter/Display.html?id=__id__">__Subject__</a>',__From__,__To__,__Status__,__Date__,__Score__,__Disposition__};
+
+unless ($Format) {
+    $Format = qq{
+        '<a href="__WebPath__/Tools/SpamFilter/Display.html?id=__id__">__id__</a>/TITLE:#',
+        '<a href="__WebPath__/Tools/SpamFilter/Display.html?id=__id__">__Subject__</a>',
+        __From__,
+        __To__,
+        __Status__,
+        __Date__,
+        __Score__
+    };
+
+    if (!$Status || $Status eq 'new') {
+        $Format .= qq{
+            __NotSpam__,
+            __Delete__
+        };
+    } elsif ($Status eq 'resolved') {
+        $Format .= qq{
+            __Delete__
+        };
+    } elsif ($Status eq 'deleted') {
+        $Format .= qq{
+            __NotSpam__
+        };
+    }
+}
 
 $Order    ||= 'ASC';
 $OrderBy  ||= 'id';
@@ -96,18 +169,36 @@ $Page = 1 unless $Page && $Page > 0;
 use RT::Spams;
 use RT::Spam;
 
-if ($Action && $emailid) {
-    my $email = RT::Spam->new($session{'CurrentUser'}) ;
-    $email->Load($emailid);
-    if ($email->id) {
-        my ($ret, $msg, $ticket);
-        if ($Action eq 'Delete') {
-            ($ret, $msg) = $email->Delete();
+if ($Delete) {
+    my @ToBeDeleted;
+    if (ref $Delete eq 'ARRAY') {
+        @ToBeDeleted = @$Delete;
+    } else {
+        push @ToBeDeleted, $Delete;
+    };
+    foreach my $id (@ToBeDeleted) {
+        my $email = RT::Spam->new($session{'CurrentUser'}) ;
+        $email->Load($id);
+        if ($email->id) {
+            my ($ret, $msg) = $email->Delete();
             if ($ret) {
                 push(@results, loc('Marked item [_1] as spam', $email->id));
             }
-        } elsif ($Action eq 'Release') {
-            ($ret, $msg, $ticket) = $email->Release(\%session);
+        }
+    }
+}
+if ($Release) {
+    my @ToBeReleased;
+    if (ref $Release eq 'ARRAY') {
+        @ToBeReleased = @$Release;
+    } else {
+        push @ToBeReleased, $Release;
+    };
+    foreach my $id (@ToBeReleased) {
+        my $email = RT::Spam->new($session{'CurrentUser'}) ;
+        $email->Load($id);
+        if ($email->id) {
+            my ($ret, $msg, $ticket) = $email->Release(\%session);
             if ($ret) {
                 push(@results, loc('Marked item [_1] as non-spam and created ticket #[_2]', $email->id, $ticket->Id));
             }
@@ -139,6 +230,6 @@ $Page => 1
 $OrderBy => undef
 $Order => undef
 $Status => 'new'
-$Action => undef,
-$emailid => undef
+$Delete => undef
+$Release => undef
 </%ARGS>

commit 677d40409c07d9bacfdd8e3f08c62e0a4f2dc537
Author: Ronaldo Richieri <ronaldo at bestpractical.com>
Date:   Fri Jul 7 16:09:39 2023 -0300

    Update POD with correct version of RT where patch was cored
    
    The required patch was added to RT 5.0.5 and not on 5.0.2.

diff --git a/lib/RT/Extension/SpamFilter.pm b/lib/RT/Extension/SpamFilter.pm
index f739dd9..3b9b02c 100644
--- a/lib/RT/Extension/SpamFilter.pm
+++ b/lib/RT/Extension/SpamFilter.pm
@@ -72,7 +72,7 @@ in your database.
 If you are upgrading this module, check for upgrading instructions
 in case changes need to be made to your database.
 
-=item Patch RT earlier than 5.0.2
+=item Patch RT earlier than 5.0.5
 
     patch -d /opt/rt5 -p1 < patches/0001-Pass-action-info-to-GetCurrentUser-for-email-interfa.patch
 

-----------------------------------------------------------------------


hooks/post-receive
-- 
rt-extension-spamfilter


More information about the Bps-public-commit mailing list