[Rt-commit] rt branch, 5.0/self-service-homepage-dashboard, created. rt-5.0.0-10-g302c1daaeb

Dianne Skoll dianne at bestpractical.com
Thu Sep 3 16:05:23 EDT 2020


The branch, 5.0/self-service-homepage-dashboard has been created
        at  302c1daaeba370c9c48ddfa3440cfa279f8d387c (commit)

- Log -----------------------------------------------------------------
commit 302c1daaeba370c9c48ddfa3440cfa279f8d387c
Author: Dianne Skoll <dianne at bestpractical.com>
Date:   Thu Sep 3 14:43:11 2020 -0400

    Add ability to serve a custom dashboard as the SelfService home page.
    
    You can enable the self-service home page dashboard in RT_SiteConfig.pm with:
    
           Set( $SelfServiceUseDashboard, 1);
    
    Note that you also need to give permissions for Everyone to see system
    dashboards.
    
    This code leverages the existing Dashboard infrastructure, but
    adds tweaks to save the self-service home page as singleton entry
    in the Attributes table, with the name "Selfservicedashboard"
    
    I made as few changes to the core Dashboards code as possible to get
    this to work; most of the work is done by RT::Dashboard::SelfService, a
    derived class from RT::Dashboard that overrides just enough of the
    database code to change the way the dashboard is loaded and stored.
    
    I did have to make some minor changes to the core dashboard files
    /Dashboards/Queries.html and lib/RT/Interface/Web.pm to get
    them to operate properly with the new class.
    
    /Dashboards/Queries.html is re-used almost as-is; an extra boolean
    parameter "self_service_dashboard" indicates that we're working on the
    self-service home page dashboard rather than a normal dashboard.
    
    For rendering the self-service page, we first verify that the
    self-service dashboard option is enabled, that the dashboard exists,
    and that it can be loaded.  If all those conditions are met, we pass
    it to /Dashboards/Render.html which has similar minor modifications
    as /Dashboards/Queries.html to handle the special-case of the self-service
    page.

diff --git a/lib/RT/Dashboard/SelfService.pm b/lib/RT/Dashboard/SelfService.pm
new file mode 100644
index 0000000000..ca33c50432
--- /dev/null
+++ b/lib/RT/Dashboard/SelfService.pm
@@ -0,0 +1,101 @@
+# BEGIN BPS TAGGED BLOCK {{{
+#
+# COPYRIGHT:
+#
+# This software is Copyright (c) 1996-2020 Best Practical Solutions, LLC
+#                                          <sales at bestpractical.com>
+#
+# (Except where explicitly superseded by other copyright notices)
+#
+#
+# LICENSE:
+#
+# This work is made available to you under the terms of Version 2 of
+# the GNU General Public License. A copy of that license should have
+# been provided with this software, but in any event can be snarfed
+# from www.gnu.org.
+#
+# This work is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+# 02110-1301 or visit their web page on the internet at
+# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html.
+#
+#
+# CONTRIBUTION SUBMISSION POLICY:
+#
+# (The following paragraph is not intended to limit the rights granted
+# to you to modify and distribute this software under the terms of
+# the GNU General Public License and is only of importance to you if
+# you choose to contribute your changes and enhancements to the
+# community by submitting them to Best Practical Solutions, LLC.)
+#
+# By intentionally submitting any modifications, corrections or
+# derivatives to this work, or any other work intended for use with
+# Request Tracker, to Best Practical Solutions, LLC, you confirm that
+# you are the copyright holder for those contributions and you grant
+# Best Practical Solutions,  LLC a nonexclusive, worldwide, irrevocable,
+# royalty-free, perpetual, license to use, copy, create derivative
+# works based on those contributions, and sublicense and distribute
+# those contributions and any derivatives thereof.
+#
+# END BPS TAGGED BLOCK }}}
+
+=head1 NAME
+
+  RT::Dashboard::SelfService - dashboard for the Self-Service Home Page
+
+=head1 SYNOPSIS
+
+  See RT::Dashboard
+
+=cut
+
+package RT::Dashboard::SelfService;
+
+use strict;
+use warnings;
+
+use base qw/RT::Dashboard/;
+
+=head2 ObjectName
+
+An object of this class is called "selfservicedashboard"
+
+=cut
+
+sub ObjectName { "selfservicedashboard" } # loc
+
+=head2 PostLoadValidate
+
+Ensure that the ID corresponds to an actual dashboard object, since it's all
+attributes under the hood.
+
+=cut
+
+sub PostLoadValidate {
+    my $self = shift;
+    return (0, "Invalid object type") unless $self->{'Attribute'}->Name eq 'Selfservicedashboard';
+    return 1;
+}
+
+sub SaveAttribute {
+    my $self   = shift;
+    my $object = shift;
+    my $args   = shift;
+
+    return $object->AddAttribute(
+        'Name'        => 'Selfservicedashboard',
+        'Description' => $args->{'Name'},
+        'Content'     => {Panes => $args->{'Panes'}},
+    );
+}
+
+RT::Base->_ImportOverlays();
+
+1;
diff --git a/lib/RT/Interface/Web.pm b/lib/RT/Interface/Web.pm
index ce7c78f679..de32934bbb 100644
--- a/lib/RT/Interface/Web.pm
+++ b/lib/RT/Interface/Web.pm
@@ -4718,7 +4718,8 @@ sub UpdateDashboard {
             return ( $ok, $msg ) = $user->SetPreferences( 'HomepageSettings', $data->{panes} );
         }
     } else {
-        my $Dashboard = RT::Dashboard->new( $session{'CurrentUser'} );
+        my $class = $args->{self_service_dashboard} ? 'RT::Dashboard::SelfService' : 'RT::Dashboard';
+        my $Dashboard = $class->new( $session{'CurrentUser'} );
         ( $ok, $msg ) = $Dashboard->LoadById($id);
 
         # report error at the bottom
diff --git a/lib/RT/Interface/Web/MenuBuilder.pm b/lib/RT/Interface/Web/MenuBuilder.pm
index 17eac59cb7..b6651b6363 100644
--- a/lib/RT/Interface/Web/MenuBuilder.pm
+++ b/lib/RT/Interface/Web/MenuBuilder.pm
@@ -1229,6 +1229,16 @@ sub _BuildAdminMenu {
         description => loc('Modify the default "RT at a glance" view'),
         path        => '/Admin/Global/MyRT.html',
     );
+    if (RT->Config->Get('SelfServiceUseDashboard')) {
+        my $self_service = $admin_global->child( selfservice_home =>
+                                                 title       => loc('Self-Service Home Page'),
+                                                 description => loc('Edit self-service home page dashboard'),
+                                                 path        => '/Admin/Global/SelfServiceHomePage.html');
+        if ( $request_path =~ m{^/Admin/Global/SelfServiceHomePage} ) {
+            $page->child(content => title => loc('Content'), path => '/Admin/Global/SelfServiceHomePage.html');
+            $page->child(show    => title => loc('Show'), path => '/SelfService');
+        }
+    }
     $admin_global->child( 'dashboards-in-menu' =>
         title       => loc('Modify Reports menu'),
         description => loc('Customize dashboards in menu'),
@@ -1571,6 +1581,7 @@ sub _BuildAdminMenu {
     }
 }
 
+#'
 sub BuildSelfServiceNav {
     my $request_path = shift;
     my $top          = shift;
@@ -1581,6 +1592,15 @@ sub BuildSelfServiceNav {
 
     my $current_user = $HTML::Mason::Commands::session{CurrentUser};
 
+    if (RT->Config->Get('SelfServiceUseDashboard')) {
+        if ($request_path =~ m{^/SelfService/index\.html$}) {
+            if ($current_user->HasRight( Right => 'ShowConfigTab',
+                                         Object => RT->System)) {
+                $page->child(content => title => loc('Content'), path => '/Admin/Global/SelfServiceHomePage.html');
+                $page->child(show    => title => loc('Show'), path => '/SelfService');
+            }
+        }
+    }
     my $queues = RT::Queues->new( $current_user );
     $queues->UnLimit;
 
@@ -1601,7 +1621,7 @@ sub BuildSelfServiceNav {
         $top->child( new => title => loc('New ticket'), path => '/SelfService/Create.html?Queue=' . $queue_id );
     }
     my $tickets = $top->child( tickets => title => loc('Tickets'), path => '/SelfService/' );
-    $tickets->child( open   => title => loc('Open tickets'),   path => '/SelfService/' );
+    $tickets->child( open   => title => loc('Open tickets'),   path => '/SelfService/Open.html' );
     $tickets->child( closed => title => loc('Closed tickets'), path => '/SelfService/Closed.html' );
 
     $top->child( "assets", title => loc("Assets"), path => "/SelfService/Asset/" )
diff --git a/share/html/SelfService/index.html b/share/html/Admin/Global/SelfServiceHomePage.html
similarity index 55%
copy from share/html/SelfService/index.html
copy to share/html/Admin/Global/SelfServiceHomePage.html
index 78d6b95a7b..17713b339e 100644
--- a/share/html/SelfService/index.html
+++ b/share/html/Admin/Global/SelfServiceHomePage.html
@@ -45,30 +45,51 @@
 %# those contributions and any derivatives thereof.
 %#
 %# END BPS TAGGED BLOCK }}}
-<& /SelfService/Elements/Header, Title => loc('Open tickets') &>
+%#<& /Elements/Header, Title => $title &>
+%#<& /Elements/Tabs &>
+%#<& /Elements/ListActions, actions => \@results &>
 
-% $m->callback(CallbackName => 'BeforeMyRequests', ARGSRef => \%ARGS, Page => $Page);
+<%INIT>
+# If custom self-service page disabled, redirect to /Admin/Global
+if (!RT->Config->Get('SelfServiceUseDashboard')) {
+    RT::Interface::Web::Redirect(RT->Config->Get('WebURL') . 'Admin/Global');
+}
 
-<& /SelfService/Elements/MyRequests,
-    %ARGS,
-    status  => '__Active__',
-    title   => loc('My open tickets'),
-    BaseURL => RT->Config->Get('WebPath') ."/SelfService/?",
-    Page    => $Page, 
-&>
+my $title = loc('Self-Service Home Page');
+my @results;
 
-% $m->callback(CallbackName => 'AfterMyRequests', ARGSRef => \%ARGS, Page => $Page);
+use RT::Dashboard::SelfService;
+my $Dashboard = RT::Dashboard::SelfService->new($session{'CurrentUser'});
 
-<& /SelfService/Elements/MyGroupRequests,
-    %ARGS,
-    status  => '__Active__',
-    title   => loc('My group\'s tickets'),
-    BaseURL => RT->Config->Get('WebPath') ."/SelfService/?",
-    Page    => $Page,
-&>
+my $dashboard_id;
 
-% $m->callback(CallbackName => 'AfterMyGroupRequests', ARGSRef => \%ARGS, Page => $Page);
+# The Self-Service Home Page dashboard is special; its attribute is
+# named "selfservicedashboard" instead of "dashboard".  We just
+# need to get an ID to reuse the rest of the dashboard code.
+my $attr = RT::Attribute->new(RT->SystemUser);
+my ($ok, $msg) = $attr->LoadByNameAndObject(Object => $RT::System,
+                                            Name => 'Selfservicedashboard');
+if (!$ok) {
+    my $blank_dashboard = {
+        Panes => {
+            body    => [],
+            sidebar => [],
+        }
+    };
+    # Doesn't exist... try creating an empty one
+    ($ok, $msg) = $Dashboard->Save(
+        Privacy => $RT::System,
+        Description => 'Self-Service Home Page Dashboard',
+        Object => $RT::System,
+        Content => $blank_dashboard);
+    unless ($ok) {
+        RT::Logger->error("Unable to create self-service home page dashboard: $msg");
+        Abort(loc("Could not create self-service home page dashboard"));
+    }
+    $dashboard_id = $Dashboard->id;
+} else {
+    $dashboard_id = $attr->Id;
+}
+$m->comp('/Dashboards/Queries.html', id => $dashboard_id, self_service_dashboard => 1, %ARGS);
 
-<%ARGS>
-$Page => 1
-</%ARGS>
+</%INIT>
diff --git a/share/html/Dashboards/Queries.html b/share/html/Dashboards/Queries.html
index 379e7b1976..87b5941b28 100644
--- a/share/html/Dashboards/Queries.html
+++ b/share/html/Dashboards/Queries.html
@@ -61,14 +61,27 @@
 <%INIT>
 my @results;
 
-use RT::Dashboard;
-my $Dashboard = RT::Dashboard->new($session{'CurrentUser'});
+# Don't permit someone to supply "self_service_dashboard=1" on the URL line
+if ($m->request_path ne '/Admin/Global/SelfServiceHomePage.html') {
+    $self_service_dashboard = 0;
+}
+
+my $class = $self_service_dashboard ? 'RT::Dashboard::SelfService' : 'RT::Dashboard';
+eval "use $class;";
+my $Dashboard = $class->new($session{'CurrentUser'});
 my ($ok, $msg) = $Dashboard->LoadById($id);
 unless ($ok) {
     RT::Logger->error("Unable to load dashboard with $id: $msg");
     Abort(loc("Could not load dashboard [_1]", $id), Code => HTTP::Status::HTTP_NOT_FOUND);
 }
-my $title = loc("Modify the content of dashboard [_1]", $Dashboard->Name);
+
+my $title;
+
+if ($self_service_dashboard) {
+    $title = loc("Modify the self-service home page");
+} else {
+    $title = loc("Modify the content of dashboard [_1]", $Dashboard->Name);
+}
 
 my @sections;
 my %item_for;
@@ -214,17 +227,32 @@ $m->callback(
 
 if ( $ARGS{UpdateSearches} ) {
     $ARGS{dashboard_id} = $id;
+    $ARGS{self_service_dashboard} = $self_service_dashboard;
     my ($ok, $msg) = UpdateDashboard( \%ARGS, \%item_for );
-    push @results, $ok ? loc('Dashboard updated') : $msg;
+    if ($self_service_dashboard) {
+        push @results, $ok ? loc('Self-service home page updated') : $msg;
+    } else {
+        push @results, $ok ? loc('Dashboard updated') : $msg;
+    }
 
+    my $path;
+    my $args;
+    if ($self_service_dashboard) {
+        $path = '/Admin/Global/SelfServiceHomePage.html';
+        $args = { };
+    } else {
+        $path = '/Dashboards/Queries.html';
+        $args = { id => $id };
+    }
     MaybeRedirectForResults(
         Actions   => \@results,
-        Path      => "/Dashboards/Queries.html",
-        Arguments => { id => $id },
+        Path      => $path,
+        Arguments => $args,
     );
 }
 
 </%INIT>
 <%ARGS>
 $id => '' unless defined $id
+$self_service_dashboard => 0 unless defined $self_service_dashboard;
 </%ARGS>
diff --git a/share/html/Dashboards/Render.html b/share/html/Dashboards/Render.html
index 18aaec7572..350ed44026 100644
--- a/share/html/Dashboards/Render.html
+++ b/share/html/Dashboards/Render.html
@@ -110,13 +110,20 @@
 my @results;
 my $skip_create = 0;
 
+# Don't permit someone to supply "self_service_dashboard=1" directly
+# on the URL line
+if ($m->request_path ne '/SelfService/index.html') {
+    $self_service_dashboard = 0;
+}
+
 $m->callback(ARGSRef => \%ARGS,
              results => \@results,
              CallbackName => 'Initial',
              skip_create => \$skip_create);
 
-use RT::Dashboard;
-my $Dashboard = RT::Dashboard->new($session{'CurrentUser'});
+my $class = $self_service_dashboard ? 'RT::Dashboard::SelfService' : 'RT::Dashboard';
+eval "use $class;";
+my $Dashboard = $class->new($session{'CurrentUser'});
 my ($ok, $msg) = $Dashboard->LoadById($id);
 unless ($ok) {
     RT::Logger->error("Unable to load dashboard with $id: $msg");
@@ -146,7 +153,12 @@ unless (defined($rows)) {
     $rows = defined($prefs->{'RowsPerPage'}) ? $prefs->{'RowsPerPage'} : 50;
 }
 
-my $title = loc '[_1] Dashboard', $Dashboard->Name;
+my $title;
+if ($self_service_dashboard) {
+    $title = loc('Self-service Dashboard');
+} else {
+    $title = loc '[_1] Dashboard', $Dashboard->Name;
+}
 
 my $show_cb = sub {
     my $pane = shift;
@@ -171,5 +183,6 @@ my $Refresh = $Preview
 $id => undef
 $Preview => 1
 $HasResults => undef
+$self_service_dashboard => 0
 </%ARGS>
 
diff --git a/share/html/SelfService/index.html b/share/html/SelfService/Open.html
similarity index 98%
copy from share/html/SelfService/index.html
copy to share/html/SelfService/Open.html
index 78d6b95a7b..83e9f768a5 100644
--- a/share/html/SelfService/index.html
+++ b/share/html/SelfService/Open.html
@@ -46,7 +46,7 @@
 %#
 %# END BPS TAGGED BLOCK }}}
 <& /SelfService/Elements/Header, Title => loc('Open tickets') &>
-
+<& /Elements/PageLayout, show_menu => 0 &>
 % $m->callback(CallbackName => 'BeforeMyRequests', ARGSRef => \%ARGS, Page => $Page);
 
 <& /SelfService/Elements/MyRequests,
diff --git a/share/html/SelfService/index.html b/share/html/SelfService/index.html
index 78d6b95a7b..15695239d5 100644
--- a/share/html/SelfService/index.html
+++ b/share/html/SelfService/index.html
@@ -45,30 +45,34 @@
 %# those contributions and any derivatives thereof.
 %#
 %# END BPS TAGGED BLOCK }}}
-<& /SelfService/Elements/Header, Title => loc('Open tickets') &>
+<%INIT>
+use RT::Dashboard::SelfService;
+if (RT->Config->Get('SelfServiceUseDashboard')) {
+    # Check if we have a self-service dashboard
+    my $Dashboard = RT::Dashboard::SelfService->new($session{'CurrentUser'});
 
-% $m->callback(CallbackName => 'BeforeMyRequests', ARGSRef => \%ARGS, Page => $Page);
+    my $dashboard_id;
 
-<& /SelfService/Elements/MyRequests,
-    %ARGS,
-    status  => '__Active__',
-    title   => loc('My open tickets'),
-    BaseURL => RT->Config->Get('WebPath') ."/SelfService/?",
-    Page    => $Page, 
-&>
+    # The Self-Service Home Page dashboard is special; its attribute is
+    # named "selfservicedashboard" instead of "dashboard".  We just
+    # need to get an ID to reuse the rest of the dashboard code.
+    my $attr = RT::Attribute->new(RT->SystemUser);
+    my ($ok, $msg) = $attr->LoadByNameAndObject(Object => $RT::System,
+                                                Name => 'Selfservicedashboard');
+    if ($ok && $attr->Id) {
+        # Try to load the dashboard
+        my ($ok, $msg) = $Dashboard->LoadById($attr->Id);
+        if ($ok) {
+            $m->comp('/Dashboards/Render.html', id => $attr->Id, self_service_dashboard => 1);
+            return;
+        }
+    }
+}
 
-% $m->callback(CallbackName => 'AfterMyRequests', ARGSRef => \%ARGS, Page => $Page);
-
-<& /SelfService/Elements/MyGroupRequests,
-    %ARGS,
-    status  => '__Active__',
-    title   => loc('My group\'s tickets'),
-    BaseURL => RT->Config->Get('WebPath') ."/SelfService/?",
-    Page    => $Page,
-&>
-
-% $m->callback(CallbackName => 'AfterMyGroupRequests', ARGSRef => \%ARGS, Page => $Page);
+# Default to old-style "My Open Tickets"
+$m->comp('/SelfService/Open.html', Page => $Page);
 
+</%INIT>
 <%ARGS>
 $Page => 1
 </%ARGS>

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


More information about the rt-commit mailing list