[Rt-commit] rt branch, 4.6-theme/admin-tools-shredder, created. rt-4.4.4-225-g3318dea30

Michel Rodriguez michel at bestpractical.com
Tue May 21 13:07:16 EDT 2019


The branch, 4.6-theme/admin-tools-shredder has been created
        at  3318dea303320a50cb145c2af9edccd77ad58618 (commit)

- Log -----------------------------------------------------------------
commit 3318dea303320a50cb145c2af9edccd77ad58618
Author: michel <michel at bestpractical.com>
Date:   Tue May 21 18:58:51 2019 +0200

    Migrate /Admin/Tools/Shredder to new theme
    
       boolean arguments now generate checkboxes
       changed the plugin help to display the first paragraph for
       each argument under the input field

diff --git a/lib/RT/Shredder/POD.pm b/lib/RT/Shredder/POD.pm
index 568d606a2..2830811db 100644
--- a/lib/RT/Shredder/POD.pm
+++ b/lib/RT/Shredder/POD.pm
@@ -83,6 +83,46 @@ sub shredder_cli
     return;
 }
 
+# Extract the help foer each argument from the plugin POD
+# they must be on a =head2 line in the ARGUMENTS section of the POD
+# the return value is a hashref:
+#   keys are the argument names,
+#   values are hash_refs: { name => <ucfirst argument name>, 
+#                           type => <from the head line>,
+#                           help => <first paragraph from the POD>
+#                         } 
+sub arguments_help {
+    my ($file) = @_;
+
+    my $text;
+    open( my $io_handle, ">:scalar", \$text ) 
+        or die "Can't open scalar for write: $!";
+    my $parser = RT::Shredder::POD::HTML->new;
+    $parser->select('ARGUMENTS');
+    $parser->parse_from_file( $file, $io_handle );
+
+    my $arguments_help = {};
+
+    while( $text=~ m{<h4[^>]*>    # argument description starts with an h4 title 
+                       \s*(\S*)   #   argument name ($1)
+                         \s*-\s*
+                       ([^<]*)    #   argument type ($2)
+                     </h4>\s*
+                       (?:<p[^>]*>\s*
+                       (.*?)      #   help: the first paragraph of the POD     ($3) 
+                     (?=</p>)
+                       )?
+                    }gsx
+          ) {
+        my( $arg, $arg_name, $type, $help)= ( lc( $1), $1, $2, $3 || '');
+        $arguments_help->{$arg}= { name => $arg_name, type => $type, help => $help };
+    } 
+  
+    return $arguments_help; 
+}
+
+1;
+
 package RT::Shredder::POD::HTML;
 use base qw(Pod::Select);
 
@@ -91,15 +131,19 @@ sub command
     my( $self, $command, $paragraph, $line_num ) = @_;
 
     my $tag;
-    if ($command =~ /^head(\d+)$/) { $tag = "h$1" }
+    # =head1 => h3, =head2 => h4
+    if ($command =~ /^head(\d+)$/) { 
+        my $h_level = $1 + 2;
+        $tag = "h$h_level";
+    }
     my $out_fh = $self->output_handle();
     my $expansion = $self->interpolate($paragraph, $line_num);
     $expansion =~ s/^\s+|\s+$//;
     $expansion = lc( $expansion );
     $expansion = ucfirst( $expansion );
 
-    print $out_fh "<$tag class=\"rt-general-header1\">" if $tag eq 'h1';
-    print $out_fh "<$tag class=\"rt-general-header2\">" if $tag eq 'h2';
+    print $out_fh "<$tag class=\"rt-general-header1\">" if $tag eq 'h3';
+    print $out_fh "<$tag class=\"rt-general-header2\">" if $tag eq 'h4';
     print $out_fh $expansion;
     print $out_fh "</$tag>" if $tag;
     print $out_fh "\n";
@@ -134,6 +178,7 @@ sub interior_sequence {
     ## Expand an interior sequence; sample actions might be:
     return "<b>$seq_argument</b>" if $seq_command eq 'B';
     return "<i>$seq_argument</i>" if $seq_command eq 'I';
+    return "<tt>$seq_argument</tt>" if $seq_command eq 'C';
     return "<span class=\"pod-sequence-$seq_command\">$seq_argument</span>";
 }
 1;
diff --git a/lib/RT/Shredder/Plugin/Attachments.pm b/lib/RT/Shredder/Plugin/Attachments.pm
index 003725467..4052b17dd 100644
--- a/lib/RT/Shredder/Plugin/Attachments.pm
+++ b/lib/RT/Shredder/Plugin/Attachments.pm
@@ -78,6 +78,13 @@ kilobytes or megabytes.
 
 sub SupportArgs { return $_[0]->SUPER::SupportArgs, qw(files_only file longer) }
 
+# used to genrate checkboxes instead of text fields in the web interface
+sub ArgIsBoolean {
+    my( $self, $arg ) = @_;
+    my %boolean_atts = map { $_ => 1 } qw( files_only );
+    return $boolean_atts{$arg};
+}
+
 sub TestArgs
 {
     my $self = shift;
diff --git a/lib/RT/Shredder/Plugin/Base.pm b/lib/RT/Shredder/Plugin/Base.pm
index 08ae1ac9f..ce4c04485 100644
--- a/lib/RT/Shredder/Plugin/Base.pm
+++ b/lib/RT/Shredder/Plugin/Base.pm
@@ -109,6 +109,17 @@ classes B<must> support.
 
 sub SupportArgs { return () }
 
+=head3 ArgIsBoolean
+
+Takes the name of an argument.
+Returns true if the argument is a boolean.
+
+Used to display checkboxes in the web interface.
+
+=cut
+
+sub ArgIsBoolean { return; }
+
 =head3 HasSupportForArgs
 
 Takes a list of argument names. Returns true if
diff --git a/lib/RT/Shredder/Plugin/Tickets.pm b/lib/RT/Shredder/Plugin/Tickets.pm
index 494bc8595..cc088960a 100644
--- a/lib/RT/Shredder/Plugin/Tickets.pm
+++ b/lib/RT/Shredder/Plugin/Tickets.pm
@@ -72,7 +72,7 @@ Arguments C<queue>, C<status> and C<updated_before> have been dropped
 as you can easy make the same search with the C<query> option.
 See examples above.
 
-=head2 with_linked - boolen
+=head2 with_linked - boolean
 
 Deletes all tickets that are linked to tickets that match L<query>.
 
@@ -86,6 +86,13 @@ See also L<with_linked>.
 
 sub SupportArgs { return $_[0]->SUPER::SupportArgs, qw(query with_linked apply_query_to_linked) }
 
+# used to genrate checkboxes instead of text fields in the web interface
+sub ArgIsBoolean {
+    my( $self, $arg ) = @_;
+    my %boolean_atts = map { $_ => 1 } qw( with_linked apply_query_to_linked );
+    return $boolean_atts{$arg};
+}
+
 sub TestArgs
 {
     my $self = shift;
diff --git a/lib/RT/Shredder/Plugin/Users.pm b/lib/RT/Shredder/Plugin/Users.pm
index a503e0d94..4e810ec9a 100644
--- a/lib/RT/Shredder/Plugin/Users.pm
+++ b/lib/RT/Shredder/Plugin/Users.pm
@@ -108,7 +108,7 @@ Email address mask.
 
 Using this option users that are members of a particular group can
 be selected for deletion. Identifier is name of user defined group
-or id of a group, as well C<Privileged> or <unprivileged> can used
+or id of a group, as well C<Privileged> or C<unprivileged> can used
 to select people from system groups.
 
 =head2 not_member_of - group identifier
@@ -153,8 +153,17 @@ want to use C<replace_relations> option.
 
 sub SupportArgs
 {
-    return $_[0]->SUPER::SupportArgs,
-           qw(status name email member_of not_member_of replace_relations no_tickets no_ticket_transactions);
+    return ( $_[0]->SUPER::SupportArgs,
+             qw( status name email member_of not_member_of replace_relations no_tickets no_ticket_transactions )
+           );
+}
+
+
+# used to genrate checkboxes instead of text fields in the web interface
+sub ArgIsBoolean {
+    my( $self, $arg ) = @_;
+    my %boolean_atts = map { $_ => 1 } qw( no_tickets no_ticket_transactions );
+    return $boolean_atts{$arg};
 }
 
 sub TestArgs
diff --git a/share/html/Admin/Tools/Shredder/Elements/ObjectCheckBox b/share/html/Admin/Tools/Shredder/Elements/ObjectCheckBox
index 08cb73508..c2a73f8f7 100644
--- a/share/html/Admin/Tools/Shredder/Elements/ObjectCheckBox
+++ b/share/html/Admin/Tools/Shredder/Elements/ObjectCheckBox
@@ -48,14 +48,16 @@
 <%ARGS>
 $Object => undef
 </%ARGS>
-<input type="checkbox" name="WipeoutObject" value="<% $Object->UID %>" />
-<span>
+<div class="custom-control custom-checkbox">
+  <input type="checkbox" name="WipeoutObject" class="custom-control-input" id="cb-<% $Object->UID %>" value="<% $Object->UID %>" />
 % if( $m->comp_exists( $path ) ) {
-% $m->comp( $path, Object => $Object );
+  <label class="custom-control-label" for="cb-<% $Object->UID %>">
+%   $m->comp( $path, Object => $Object );
 % } else {
-<% $Object->UID %>
+    <% $Object->UID %>
 % }
-</span><br />
+  </label>
+</div>
 <%ONCE>
 require File::Spec;
 </%ONCE>
diff --git a/share/html/Admin/Tools/Shredder/Elements/PluginArguments b/share/html/Admin/Tools/Shredder/Elements/PluginArguments
index 987cb9dc6..c6d250dab 100644
--- a/share/html/Admin/Tools/Shredder/Elements/PluginArguments
+++ b/share/html/Admin/Tools/Shredder/Elements/PluginArguments
@@ -49,19 +49,55 @@
 $Plugin => ''
 </%ARGS>
 <div id="shredder-plugin-<% $Plugin %>-arguments" class="shredder-form">
-<span><% loc('Fill arguments') %>:</span><br />
-<table>
+<&| /Widgets/TitleBox, title => loc("Search") &>
 % for my $a ( $plugin_obj->SupportArgs ) {
-<tr>
-    <td class="label"><label for="<% "$Plugin:$a" %>"><% loc($a) %>:</label></td>
-    <td><input type="text" name="<% "$Plugin:$a" %>" id="<% "$Plugin:$a" %>" value="<% $ARGS{ "$Plugin:$a" } || '' %>" /></td>
-</tr>
+  <div class="form-row">
+%  if( $plugin_obj->ArgIsBoolean( $a ) ) {
+    <div class="col-md-9 offset-md-2">
+      <div class="custom-control custom-checkbox">
+        <input type="checkbox" id="<% "$Plugin:$a" %>" name="<% "$Plugin:$a" %>" class="custom-control-input" value="<% $ARGS{ "$Plugin:$a" } || '' %>" />
+        <label class="custom-control-label" for="<% "$Plugin:$a" %>"><% loc($a) %></label>
+        <span class="hints"><% $arguments_help{$a}->{help} |n%></span>
+      </div>
+    </div>
+%  } else {
+    <div class="col-md-2 label"><% loc($a) %></div>
+    <div class="col-md-10 value">
+      <input type="text" name="<% "$Plugin:$a" %>" id="<% "$Plugin:$a" %>" class="form-control" value="<% $ARGS{ "$Plugin:$a" } || '' %>" />
+%     if( $arguments_help{$a} ) {
+          <span class="hints"><% $arguments_help{$a}->{type} . ' - ' . $arguments_help{$a}->{help} |n%></span>
+%     }
+    </div>
+%  }
+  </div>
 % }
-</table>
+  <div id="shredder-submit-button" class="<% $Plugin? '': 'hidden' %>">
+  <& /Elements/Submit, Name => 'Search', Label => loc('Search') &>
+  </div>
+  </&>
 </div>
 <%INIT>
 use RT::Shredder::Plugin;
+use RT::Shredder::POD;
+
+my $base_obj = RT::Shredder::Plugin->new;
+
+my %plugins = $base_obj->List;
+
+my $base_file = $plugins{ 'Base' };
+$base_file =~ s/\.pm$/\/Search.pm/; # docs for the Base "plugin" is in the base file, not Search.pm
+my $base_arguments_help = RT::Shredder::POD::arguments_help( $base_file);
+
 my $plugin_obj = RT::Shredder::Plugin->new;
+
 my ($status, $msg) = $plugin_obj->LoadByName( $Plugin );
 die $msg unless $status;
+
+my $plugin_file = $plugins{ $Plugin };
+unless( $plugin_file ) {
+    $RT::Logger->error( "Couldn't find plugin '$Plugin'" );
+    return;
+}
+my $plugin_arguments_help = RT::Shredder::POD::arguments_help( $plugin_file);
+my %arguments_help = ( %$base_arguments_help, %$plugin_arguments_help );
 </%INIT>
diff --git a/share/html/Admin/Tools/Shredder/Elements/PluginHelp b/share/html/Admin/Tools/Shredder/Elements/PluginHelp
index 280ea8b76..c5696893a 100644
--- a/share/html/Admin/Tools/Shredder/Elements/PluginHelp
+++ b/share/html/Admin/Tools/Shredder/Elements/PluginHelp
@@ -49,7 +49,9 @@
 $Plugin => ''
 </%ARGS>
 <div id="shredder-plugin-<% $Plugin %>-help" class="shredder-help">
-<% $text |n%>
+  <&| /Widgets/TitleBox, title => loc("$Plugin Help") &>
+    <% $text |n%>
+  </&>
 </div>
 <%ONCE>
 use RT::Shredder::Plugin;
diff --git a/share/html/Admin/Tools/Shredder/Elements/SelectObjects b/share/html/Admin/Tools/Shredder/Elements/SelectObjects
index 7636dee82..240c420e6 100644
--- a/share/html/Admin/Tools/Shredder/Elements/SelectObjects
+++ b/share/html/Admin/Tools/Shredder/Elements/SelectObjects
@@ -49,19 +49,24 @@
 @Objects => ()
 </%ARGS>
 <div id="shredder-plugin-results">
+  <&| /Widgets/TitleBox, title => loc("Results") &>
+
 % unless( @Objects ) {
-<& /Elements/ListActions, actions => [loc("Objects list is empty")] &>
+    <& /Elements/ListActions, actions => [loc("Objects list is empty")] &>
 % } else {
-<div class="shredder-form">
-<input id="shredder-select-all-objects-checkbox" type="checkbox" name="SelectAllObjects" onclick="checkAllObjects()" />
-<span><% loc("click to check/uncheck all objects at once") %></span>
-<hr />
+    <div class="shredder-form">
+      <div class="custom-control custom-checkbox">
+        <input id="shredder-select-all-objects-checkbox" type="checkbox" name="SelectAllObjects" class="custom-control-input" onclick="checkAllObjects()" />
+        <label class="custom-control-label" for="shredder-select-all-objects-checkbox"><% loc("click to check/uncheck all objects at once") %></label>
+      </div>
+      <hr />
 % foreach my $o( @Objects ) {
-<& ObjectCheckBox, Object => $o &>
+      <& ObjectCheckBox, Object => $o &>
 % }
-</div>
-<& /Elements/Submit, Name => 'Wipeout', Label => loc('Wipeout') &>
+      <& /Elements/Submit, Name => 'Wipeout', Label => loc('Wipeout') &>
+    </div>
 % }
+  </&>
 </div>
 <%INIT>
 </%INIT>
diff --git a/share/html/Admin/Tools/Shredder/Elements/SelectPlugin b/share/html/Admin/Tools/Shredder/Elements/SelectPlugin
index 1db5ec924..c02c7eddb 100644
--- a/share/html/Admin/Tools/Shredder/Elements/SelectPlugin
+++ b/share/html/Admin/Tools/Shredder/Elements/SelectPlugin
@@ -51,7 +51,7 @@ $Plugin => ''
 <& PluginHelp, %ARGS, Plugin => 'Base' &>
 <div class="shredder-form">
 <span>Select plugin: </span>
-<select name="Plugin" onchange="showShredderPluginTab(this.value);">
+<select name="Plugin" class="form-control selectpicker" onchange="showShredderPluginTab(this.value);">
 <option value=""><% loc('(no value)') %></option>
 % foreach my $p( keys %plugins ) {
 <option value="<% $p %>" <% ($p eq $Plugin)? 'selected="selected"': '' %>><% loc($p) %></option>
@@ -61,8 +61,8 @@ $Plugin => ''
 <div id="shredder-plugin-tabs">
 % foreach my $p( keys %plugins ) {
 <div id="shredder-plugin-<% $p %>-tab" class="<% ($p ne $Plugin)? 'hidden': '' %>">
-<& PluginHelp, %ARGS, Plugin => $p &>
-<& PluginArguments, %ARGS, Plugin => $p &>
+  <& PluginHelp, %ARGS, Plugin => $p &>
+  <& PluginArguments, %ARGS, Plugin => $p &>
 </div>
 % }
 </div>
diff --git a/share/html/Admin/Tools/Shredder/index.html b/share/html/Admin/Tools/Shredder/index.html
index 557d5da64..08f4a9af4 100644
--- a/share/html/Admin/Tools/Shredder/index.html
+++ b/share/html/Admin/Tools/Shredder/index.html
@@ -59,9 +59,6 @@ $Wipeout => ''
 <& /Elements/ListActions, actions => $messages{'Success'} &>
 <& Elements/DumpFileLink, File => $dump_file &>
 <& Elements/SelectPlugin, Plugin => $Plugin, %ARGS &>
-<div id="shredder-submit-button" class="<% $Plugin? '': 'hidden' %>">
-<& /Elements/Submit, Name => 'Search', Label => loc('Search') &>
-</div>
 </div>
 <br />
 % if( $Search || $Wipeout ) {

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


More information about the rt-commit mailing list