[Rt-commit] rt branch 5.0/dashboard-test-email-button created. rt-5.0.3-23-g11684084ac

BPS Git Server git at git.bestpractical.com
Thu Jul 21 18:18:17 UTC 2022


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".

The branch, 5.0/dashboard-test-email-button has been created
        at  11684084ace754fcb4b69aa4291e005d5a20bb43 (commit)

- Log -----------------------------------------------------------------
commit 11684084ace754fcb4b69aa4291e005d5a20bb43
Author: sunnavy <sunnavy at bestpractical.com>
Date:   Mon May 16 22:04:51 2022 +0800

    Support to send dashboard emails for testing on Subscription page

diff --git a/etc/RT_Config.pm.in b/etc/RT_Config.pm.in
index c6320ac8c5..ff2c4862ad 100644
--- a/etc/RT_Config.pm.in
+++ b/etc/RT_Config.pm.in
@@ -888,6 +888,15 @@ See also L</@LexiconLanguages>.
 
 Set(@EmailDashboardLanguageOrder, qw(_subscription _recipient _subscriber en));
 
+=item C<$DashboardTestEmailLimit>
+
+The max number of recipients dashboard's test email can be sent to at one time.
+Default is 50.
+
+=cut
+
+Set($DashboardTestEmailLimit, 50);
+
 =back
 
 
diff --git a/lib/RT/Config.pm b/lib/RT/Config.pm
index 89276eeba7..3805af37f6 100644
--- a/lib/RT/Config.pm
+++ b/lib/RT/Config.pm
@@ -1818,6 +1818,9 @@ our %META;
     BcryptCost => {
         Widget => '/Widgets/Form/Integer',
     },
+    DashboardTestEmailLimit => {
+        Widget => '/Widgets/Form/String',
+    },
     DefaultSummaryRows => {
         Widget => '/Widgets/Form/Integer',
     },
diff --git a/lib/RT/Dashboard/Mailer.pm b/lib/RT/Dashboard/Mailer.pm
index 1fe1f54e12..02d07b4bbf 100644
--- a/lib/RT/Dashboard/Mailer.pm
+++ b/lib/RT/Dashboard/Mailer.pm
@@ -71,6 +71,8 @@ sub MailDashboards {
         Time   => time,
         User   => undef,
         Recipients => undef,
+        Subscription => undef,
+        Test => 0,
         @_,
     );
 
@@ -115,6 +117,10 @@ sub MailDashboards {
         }
     }
 
+    if ( $args{Subscription} ) {
+        $Users->Limit( FIELD => 'id', VALUE => $args{Subscription}->Object->Id || 0 );
+    }
+
     while (defined(my $user = $Users->Next)) {
         my ($hour, $dow, $dom) = HourDowDomIn($args{Time}, $user->Timezone || RT->Config->Get('Timezone'));
         $hour .= ':00';
@@ -127,7 +133,8 @@ sub MailDashboards {
 
         # look through this user's subscriptions, are any supposed to be generated
         # right now?
-        for my $subscription ($user->Attributes->Named('Subscription')) {
+        my @subscriptions = $args{Subscription} || $user->Attributes->Named('Subscription');
+        for my $subscription (@subscriptions) {
             next unless $self->IsSubscriptionReady(
                 %args,
                 Subscription => $subscription,
@@ -243,7 +250,7 @@ sub MailDashboards {
                 }
             }
 
-            if ($email_success) {
+            if ( $email_success && !$args{Test} ) {
                 my $counter = $subscription->SubValue('Counter') || 0;
                 $subscription->SetSubValues(Counter => $counter + 1)
                     unless $args{DryRun};
@@ -259,10 +266,11 @@ sub IsSubscriptionReady {
         Subscription => undef,
         User         => undef,
         LocalTime    => [0, 0, 0],
+        Test         => 0,
         @_,
     );
 
-    return 1 if $args{All};
+    return 1 if $args{All} || $args{Test};
 
     my $subscription  = $args{Subscription};
 
diff --git a/share/html/Dashboards/Subscription.html b/share/html/Dashboards/Subscription.html
index e65c2c0a4d..e4e7928ff4 100644
--- a/share/html/Dashboards/Subscription.html
+++ b/share/html/Dashboards/Subscription.html
@@ -297,6 +297,70 @@
 % }
     </div>
   </div>
+
+% if ($SubscriptionObj) {
+  <&| /Widgets/TitleBox, title => loc('Test Dashboard Subscription') &>
+    <p class="mt-3 ml-3">
+      <&|/l&>Your dashboard subscription will run automatically using the schedule defined above. This section allows you to manually test sending a dashboard email. Click Show above to view the content of the dashboard without sending email.</&>
+    </p>
+    <div class="form-row">
+      <div class="label col-3">
+        <&|/l&>Send test email to</&>:
+      </div>
+      <div class="value col-9">
+        <div class="custom-control custom-radio">
+          <input type="radio" id="send-test-email-type-me" name="SendTestEmailType" class="custom-control-input" value="me" <% ($ARGS{'SendTestEmailType'} || '') eq 'me' ? ' checked="checked"': '' |n %>>
+          <label class="custom-control-label" for="send-test-email-type-me"><% $session{CurrentUser}->EmailAddress %></label>
+        </div>
+        <div class="custom-control custom-radio">
+          <input type="radio" id="send-test-email-type-custom" name="SendTestEmailType" class="custom-control-input" value="custom" <% ($ARGS{'SendTestEmailType'} || '') eq 'custom' ? ' checked="checked"': '' |n %>>
+          <label class="custom-control-label d-inline-block has-text-input" for="send-test-email-type-custom">
+            <&|/l&>One email address</&>:
+            <input class="form-control w-auto d-inline-block" name="SendTestEmailToCustom" value="<% ($ARGS{'SendTestEmailToCustom'} || '') %>" />
+          </label>
+        </div>
+        <div class="custom-control custom-radio">
+          <input type="radio" id="send-test-email-type-first" name="SendTestEmailType" class="custom-control-input" value="first" <% ($ARGS{'SendTestEmailType'} || '') eq 'first' ? ' checked="checked"': '' |n %>>
+          <label class="custom-control-label d-inline-block has-text-input" for="send-test-email-type-first">
+            <&|/l_unsafe, qq!<input size="2" type="number" min="1" max="@{[ RT->Config->Get('DashboardTestEmailLimit') || 50 ]}" class="form-control w-auto d-inline-block" name="SendTestEmailToFirst" value="@{[ $ARGS{'SendTestEmailToFirst'} || 1 ]}" />! &>First [_1] recipient(s) from the list above</&>
+          </label>
+        </div>
+        <input name="SendTestEmailToFirstRecipients" type="hidden" value="" />
+        <div class="send-test-email-type-first-details hidden">
+          <p class="mt-1 mb-0 ml-4"><&|/l&>Recipient list</&>:</p>
+          <ol class="list-group-compact">
+%         for my $user ( @current_recipient_list ) {
+            <li class="list-group-item marker" data-id="<% $user->Id %>">
+              <& /Elements/ShowUser, User => $user, LinkTarget => '_blank' &>
+            </li>
+%         }
+          </ol>
+        </div>
+      </div>
+    </div>
+    <div class="form-row">
+      <div class="col-12">
+        <& /Elements/Submit, Name => 'SendTestEmail', Label => loc('Send Test Email') &>
+      </div>
+    </div>
+    <script type="text/javascript">
+        jQuery('input[name=SendTestEmailType]').change(function() {
+            jQuery('.send-test-email-type-first-details').toggleClass('hidden', jQuery(this).val() !== 'first');
+        }).filter(':checked').change();
+
+        jQuery('input[name=SendTestEmailToFirst]').change(function() {
+            var selected = jQuery('.send-test-email-type-first-details li').slice(0, jQuery(this).val());
+            selected.removeClass('hidden');
+            jQuery('input[name=SendTestEmailToFirstRecipients]').val(
+                selected.map(function() { return jQuery(this).data('id') }).get().join(',')
+            );
+
+            jQuery('.send-test-email-type-first-details li').slice(jQuery(this).val()).addClass('hidden');
+        }).change();
+    </script>
+  </&>
+% }
+
 </form>
 
 <%INIT>
@@ -463,10 +527,92 @@ if (defined $ARGS{Save}) {
     $UserString = undef;
     $UserField = undef;
     $UserOp = undef;
+} elsif ( $ARGS{SendTestEmail} ) {
+    if ($SubscriptionObj) {
+        if ( my $type = $ARGS{SendTestEmailType} ) {
+            my @recipients;
+            if ( $type eq 'me' ) {
+                push @recipients, $session{CurrentUser}->EmailAddress;
+            }
+            elsif ( $type eq 'custom' ) {
+                if ( $ARGS{SendTestEmailToCustom} ) {
+                    push @recipients, $ARGS{SendTestEmailToCustom};
+                }
+                else {
+                    push @results, loc('Empty email address');
+                }
+            }
+            elsif ( $type eq 'first' ) {
+                if ( my $emails = $ARGS{SendTestEmailToFirstRecipients} ) {
+                    @recipients = split /,/, $emails;
+                    my $limit = RT->Config->Get('DashboardTestEmailLimit') || 50;
+                    if ( @recipients > $limit ) {
+                        push @results, loc( 'Number of recipients exceeds limit([_1])', $limit );
+                        @recipients = ();
+                    }
+                }
+                else {
+                    push @results, loc('Empty number of recipients');
+                }
+            }
+            else {
+                # should not be here
+            }
+
+            if (@recipients) {
+                require RT::Dashboard::Mailer;
+                RT::Dashboard::Mailer->MailDashboards(
+                    Subscription => $SubscriptionObj,
+                    Test         => 1,
+                    Recipients   => \@recipients,
+                );
+                push @results, loc('Sent test email');
+            }
+        }
+    }
 }
 
+my @current_recipient_list;
+
 if ($SubscriptionObj) {
     $title = loc("Modify the subscription to dashboard [_1]", $Dashboard->Name);
+
+    my %exist;
+    push @current_recipient_list, $session{CurrentUser}->UserObj;
+    $exist{$session{CurrentUser}->Id} = 1;
+
+    my $limit = RT->Config->Get('DashboardTestEmailLimit') || 50;
+
+    if ( @current_recipient_list < $limit ) {
+        for my $user_id ( @{$fields{Recipients}{Users} || []} ) {
+            next if $exist{$user_id}++;
+
+            my $user = RT::User->new($session{CurrentUser});
+            $user->Load($user_id);
+            if ( $user->Id && !$user->Disabled ) {
+                push @current_recipient_list, $user;
+                last if @current_recipient_list == $limit;
+            }
+        }
+    }
+
+    if ( @current_recipient_list < $limit ) {
+        for my $group_id ( @{ $fields{Recipients}{Groups} || [] } ) {
+            my $group = RT::Group->new( $session{CurrentUser} );
+            $group->Load($group_id);
+            if ( $group->Id ) {
+                my $users = $group->UserMembersObj;
+                while ( my $user = $users->Next ) {
+                    next if $exist{ $user->Id }++;
+                    push @current_recipient_list, $user;
+                    last if @current_recipient_list == $limit;
+                }
+            }
+            else {
+                RT->Logger->warning("Couldn't load group $group_id");
+            }
+        }
+    }
 }
 else {
     $title = loc("Subscribe to dashboard [_1]", $Dashboard->Name);
diff --git a/share/static/css/elevator-light/forms.css b/share/static/css/elevator-light/forms.css
index 2bfcc777f8..08c1b1b1a6 100644
--- a/share/static/css/elevator-light/forms.css
+++ b/share/static/css/elevator-light/forms.css
@@ -310,6 +310,11 @@ span.current-value.form-control {
   height: auto;
 }
 
+.custom-control-label.has-text-input::before,
+.custom-control-label.has-text-input::after {
+  top: 0.5rem;
+}
+
 /* Assets widget in ticket display */
 form span.current-value {
   display: block;
@@ -329,6 +334,11 @@ form span.current-value {
   padding: 0.25em;
 }
 
+/* show markers like 1. 2. 3. for lists */
+.list-group-item.marker {
+  display: list-item;
+}
+
 .bootstrap-select button:focus {
   background: #f8f9fa;
 }

commit ff71e1713fa1f8ca567671cbe9afe5baa7cfe456
Author: sunnavy <sunnavy at bestpractical.com>
Date:   Fri Oct 15 02:03:02 2021 +0800

    Add --recipient to send dashboard emails to specified recipients
    
    This is useful when debugging dashboard emails for specific users.

diff --git a/lib/RT/Dashboard/Mailer.pm b/lib/RT/Dashboard/Mailer.pm
index 5eca55a391..1fe1f54e12 100644
--- a/lib/RT/Dashboard/Mailer.pm
+++ b/lib/RT/Dashboard/Mailer.pm
@@ -70,6 +70,7 @@ sub MailDashboards {
         DryRun => 0,
         Time   => time,
         User   => undef,
+        Recipients => undef,
         @_,
     );
 
@@ -88,6 +89,32 @@ sub MailDashboards {
         $Users->Limit( FIELD => 'id', VALUE => $user->Id || 0 );
     }
 
+    my @recipients;
+    my %recipient_language;
+
+    if ( $args{Recipients} ) {
+        for my $recipient ( ref $args{Recipients} eq 'ARRAY' ? @{ $args{Recipients} } : $args{Recipients} ) {
+            my $user = RT::User->new( RT->SystemUser );
+            $user->Load($recipient);
+            if ( !$user->Id && $recipient =~ /@/ ) {
+                $user->LoadOrCreateByEmail($recipient);
+            }
+
+            if ( $user->Id ) {
+                if ( $user->Disabled ) {
+                    RT->Logger->error("User $recipient is disabled, exiting");
+                    return;
+                }
+                push @recipients, $user->EmailAddress;
+                $recipient_language{ $user->EmailAddress } = $user->Lang;
+            }
+            else {
+                RT->Logger->error("Could not load user $recipient, exiting");
+                return;
+            }
+        }
+    }
+
     while (defined(my $user = $Users->Next)) {
         my ($hour, $dow, $dom) = HourDowDomIn($args{Time}, $user->Timezone || RT->Config->Get('Timezone'));
         $hour .= ':00';
@@ -108,33 +135,38 @@ sub MailDashboards {
                 LocalTime    => [$hour, $dow, $dom],
             );
 
-            my $recipients = $subscription->SubValue('Recipients');
-            my $recipients_users = $recipients->{Users};
-            my $recipients_groups = $recipients->{Groups};
 
             my @emails;
-            my %recipient_language;
 
-            # add users' emails to email list
-            for my $user_id (@{ $recipients_users || [] }) {
-                my $user = RT::User->new(RT->SystemUser);
-                $user->Load($user_id);
-                next unless $user->id and !$user->Disabled;
-
-                push @emails, $user->EmailAddress;
-                $recipient_language{$user->EmailAddress} = $user->Lang;
+            if ( @recipients ) {
+                @emails = @recipients;
             }
+            else {
+                my $recipients = $subscription->SubValue('Recipients');
+                my $recipients_users = $recipients->{Users};
+                my $recipients_groups = $recipients->{Groups};
 
-            # add emails for every group's members
-            for my $group_id (@{ $recipients_groups || [] }) {
-                my $group = RT::Group->new(RT->SystemUser);
-                $group->Load($group_id);
-                next unless $group->id;
+                # add users' emails to email list
+                for my $user_id (@{ $recipients_users || [] }) {
+                    my $user = RT::User->new(RT->SystemUser);
+                    $user->Load($user_id);
+                    next unless $user->id and !$user->Disabled;
 
-                my $users = $group->UserMembersObj;
-                while (my $user = $users->Next) {
                     push @emails, $user->EmailAddress;
-                    $recipient_language{$user->EmailAddress} = $user->Lang;
+                    $recipient_language{ $user->EmailAddress } = $user->Lang;
+                }
+
+                # add emails for every group's members
+                for my $group_id (@{ $recipients_groups || [] }) {
+                    my $group = RT::Group->new(RT->SystemUser);
+                    $group->Load($group_id);
+                    next unless $group->id;
+
+                    my $users = $group->UserMembersObj;
+                    while (my $user = $users->Next) {
+                        push @emails, $user->EmailAddress;
+                        $recipient_language{ $user->EmailAddress } = $user->Lang;
+                    }
                 }
             }
 
diff --git a/sbin/rt-email-dashboards.in b/sbin/rt-email-dashboards.in
index 469c9208ec..1eb540445c 100644
--- a/sbin/rt-email-dashboards.in
+++ b/sbin/rt-email-dashboards.in
@@ -70,7 +70,7 @@ BEGIN { # BEGIN RT CMD BOILERPLATE
 my %opts;
 use Getopt::Long;
 GetOptions( \%opts,
-    "help|h", "dryrun", "time=i", "epoch=i", "all", "log=s", "user=s"
+    "help|h", "dryrun", "time=i", "epoch=i", "all", "log=s", "user=s", "recipient=s@"
 );
 
 if ($opts{'help'}) {
@@ -104,6 +104,7 @@ RT::Dashboard::Mailer->MailDashboards(
     DryRun => $opts{dryrun},
     Time   => ($opts{time} || $opts{epoch} || time), # epoch is the old-style
     User   => $opts{user},
+    Recipients => $opts{recipient},
     Opts   => \%opts,
 );
 
@@ -170,6 +171,14 @@ used with --dryrun for testing and debugging)
 
 Only check the specified user's subscriptions
 
+=item --recipient User NAME or EMAIL or ID
+
+Only send emails to the specified user.
+
+Could be specified multiple times to send multiple emails, e.g.
+
+     --recipient alice at example.com --recipient bob at example.com
+
 =item --log LEVEL
 
 Adjust LogToSTDERR config option

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


hooks/post-receive
-- 
rt


More information about the rt-commit mailing list