[Rt-commit] rt branch 5.0/dashboard-test-email-button created. rt-5.0.3-23-gc5cea50524
BPS Git Server
git at git.bestpractical.com
Tue Jul 26 12:52:19 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 c5cea5052450c372f4720b1fed481560928a3ed5 (commit)
- Log -----------------------------------------------------------------
commit c5cea5052450c372f4720b1fed481560928a3ed5
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..19b71011e6 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 maximum number of dashboard test emails that can be sent in a
+single test. 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..9dd3a3cbfd 100644
--- a/share/html/Dashboards/Subscription.html
+++ b/share/html/Dashboards/Subscription.html
@@ -297,6 +297,74 @@
% }
</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 no-text-input">
+ <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">Me (<% $session{CurrentUser}->EmailAddress %>)</label>
+ </div>
+ <div class="custom-control custom-radio has-text-input">
+ <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" 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 has-text-input">
+ <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" for="send-test-email-type-first">
+%# Make input a bit wider if possible to not squeeze content too much
+% my $max = RT->Config->Get('DashboardTestEmailLimit') || 50;
+ <&|/l_unsafe,
+ qq!<input size="@{[1+length $max]}" type="number" min="1" max="@{[ $max ]}" class="form-control w-auto d-inline-block" name="SendTestEmailToFirst" value="@{[ $ARGS{'SendTestEmailToFirst'} || 1 ]}" />!,
+ $max, &>First [_1] recipient(s) from the list above (Max: [_2])</&>
+ </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 +531,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..3eca1af77a 100644
--- a/share/static/css/elevator-light/forms.css
+++ b/share/static/css/elevator-light/forms.css
@@ -310,6 +310,18 @@ span.current-value.form-control {
height: auto;
}
+/* Align radio inputs with labels */
+.custom-control.has-text-input label::before,
+.custom-control.has-text-input label::after {
+ top: 0.6rem;
+}
+
+/* Make radio options without inputs in labels the same height as ones that have inputs in labels */
+.custom-control.no-text-input {
+ height: calc(1.5em + 0.75rem + 2px); /* the same as .form-control input */
+ padding-top: 5px;
+}
+
/* Assets widget in ticket display */
form span.current-value {
display: block;
@@ -329,6 +341,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