Skip to content

Commit

Permalink
Merge branch '6.0/dashboard-layouts'
Browse files Browse the repository at this point in the history
  • Loading branch information
cbrandtbuffalo committed Oct 9, 2024
2 parents 8e0f1e9 + 35eee5b commit cd5e7b4
Show file tree
Hide file tree
Showing 44 changed files with 889 additions and 848 deletions.
2 changes: 1 addition & 1 deletion docs/customizing/assets/tutorial.pod
Original file line number Diff line number Diff line change
Expand Up @@ -278,7 +278,7 @@ status. Then when the ticket is resolved, flip it back to 'in-use'.
If an end user contacts us with some problem with their laptop, RT makes it
easy to find the correct laptop record and create a ticket for them. Since our
support staff do this frequently, they have added the Find User portlet to
their RT at a glance page and can quickly search for the user and go to their
their homepage and can quickly search for the user and go to their
User Summary page.

We have added the Assigned Assets portlet to the User Summary page, so the
Expand Down
12 changes: 6 additions & 6 deletions docs/dashboards.pod
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@ outstanding invoice tickets.
There are several different rights you can grant to allow users access to the
features described here. These rights are described in L</"Dashboard Rights">.

=head2 RT at a glance
=head2 Homepage

RT's homepage, called RT at a glance, is a dashboard that has been set as your
RT's homepage is a dashboard that has been set as your
current homepage. By default, all users see the system-level dashboard set by
the RT administrator. If you have the "ModifySelf" right, you can easily change your
homepage by clicking on the gear icon. You'll see a page showing you all dashboards
Expand Down Expand Up @@ -86,7 +86,7 @@ F<docs/images/dashboard-content-invoices.png>]
F<docs/images/dashboard-content-invoices.png>]

Click Show in the submenu and you'll see your new dashboard. Click Home to
return to the "RT at a glance" page and you'll see your new dashboard is in the
return to the "Homepage" page and you'll see your new dashboard is in the
Dashboards portlet on the right side of the page.

On dashboard pages, you can click on the title of any section and go to the
Expand Down Expand Up @@ -130,9 +130,9 @@ the Components section when you create and modify dashboards.

=head2 Dashboard Menu Entries

In addition to having dashboards available on the "RT at a glance" page, you
can also add them to the Reports menu. To modify the Reports menu, select Reports >
"Update This Menu" or "Logged in as" > Settings > "Dashboards in menu". You'll
In addition to having dashboards available on the homepage, you
can also add them to the Reports menu. To modify the Reports menu, select Reports >
"Update This Menu" or "Logged in as" > Settings > "Dashboards in menu". You'll
see the Customize dashboard page which is similar to the Dashboard Content page.

=for html <img alt="Customize dashboard menu"
Expand Down
2 changes: 1 addition & 1 deletion docs/working_with_rt.pod
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ the subject, the message and various custom fields. These available fields
are customized by your RT administrator. You can also add attachments to
the ticket by either dragging and dropping the file or clicking to select
a file from your computer. Another way tickets can be created is by using
the "Quick ticket creation" portlet on the "RT at a glance" page. Rather
the "Quick ticket creation" portlet on the homepage. Rather
than jumping to an additional page, this portlet allows to add the most
prominent information on a ticket without leaving your home page. Note that
this portlet may not be available if your RT administrator removed it. With
Expand Down
2 changes: 1 addition & 1 deletion etc/RT_Config.pm.in
Original file line number Diff line number Diff line change
Expand Up @@ -2732,7 +2732,7 @@ Set($HomePageRefreshInterval, 0);
=item C<$HomepageComponents>

C<$HomepageComponents> is an arrayref of allowed components on a
user's customized homepage ("RT at a glance").
user's customized homepage.

=cut

Expand Down
66 changes: 34 additions & 32 deletions etc/initialdata
Original file line number Diff line number Diff line change
Expand Up @@ -1009,10 +1009,9 @@ The following tokens will expire within the next 7 days:
if ($search) {
push @searches,
{
pane => 'body',
portlet_type => 'search',
id => $search->Id,
description => "Saved Search: $search_name",
description => "Ticket: $search_name",
privacy => join( '-', ref( RT->System ), RT->System->Id ),
};
}
Expand All @@ -1021,40 +1020,43 @@ The following tokens will expire within the next 7 days:
}
}

my $panes = {
body => [
@searches,
{ pane => 'body',
portlet_type => 'component',
component => 'QuickCreate',
description => 'QuickCreate',
path => '/Elements/QuickCreate',
},
my @elements = {
Layout => 'col-md-8,col-md-4',
Elements => [
[
@searches,
{
portlet_type => 'component',
component => 'QuickCreate',
description => 'QuickCreate',
path => '/Elements/QuickCreate',
},
],
[
{
portlet_type => 'component',
component => 'MyReminders',
description => 'MyReminders',
path => '/Elements/MyReminders',
},
{
portlet_type => 'component',
component => 'QueueList',
description => 'QueueList',
path => '/Elements/QueueList',
},
{
portlet_type => 'component',
component => 'Dashboards',
description => 'Dashboards',
path => '/Elements/Dashboards',
},
]
],
sidebar => [
{ pane => 'sidebar',
portlet_type => 'component',
component => 'MyReminders',
description => 'MyReminders',
path => '/Elements/MyReminders',
},
{ pane => 'sidebar',
portlet_type => 'component',
component => 'QueueList',
description => 'QueueList',
path => '/Elements/QueueList',
},
{ pane => 'sidebar',
portlet_type => 'component',
component => 'Dashboards',
description => 'Dashboards',
path => '/Elements/Dashboards',
},
]
};

# fill content
my ( $ret, $msg ) = $dashboard->Update( Panes => $panes );
my ( $ret, $msg ) = $dashboard->Update( Elements => \@elements );
if ( !$ret ) {
RT->Logger->error("Couldn't update content for dashboard Homepage: $msg");
}
Expand Down
85 changes: 85 additions & 0 deletions etc/upgrade/5.9.1/content
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
use strict;
use warnings;

our @Final = (
sub {

# Previously only the corresponding panes in inner dashboards were
# rendered. New layout is much more flexible and there are no
# correponding panes, so here we expand inner dashboards to make the
# content the same as before.

my $attrs = RT::Attributes->new( RT->SystemUser );
$attrs->Limit( FIELD => 'Name', VALUE => [ 'Dashboard', 'SelfServiceDashboard' ], OPERATOR => 'IN' );
while ( my $attr = $attrs->Next ) {
my $content = $attr->Content;
if ( $content && $content->{Panes} ) {
my $new_content = {};
my $changed;
for my $pane ( sort keys %{ $content->{Panes} } ) {
my @new_panes;
for my $portlet ( @{ $content->{Panes}->{$pane} } ) {
if ( $portlet->{portlet_type} eq 'dashboard' ) {
$changed ||= 1;
my $dashboard = RT::Attribute->new( RT->SystemUser );
$dashboard->Load( $portlet->{id} );
if ( $dashboard->Id ) {
push @new_panes, @{ $dashboard->Content->{'Panes'}{$pane} || [] }
if $dashboard->Content;
}
else {
RT->Logger->error(
"Couldn't find dashboard $portlet->{id}, removing from dashboard #"
. $attr->Id );
}
}
else {
push @new_panes, $portlet;
}
}
$content->{Panes}->{$pane} = \@new_panes;
}
if ($changed) {
my ( $ret, $msg ) = $attr->SetContent($content);
RT->Logger->error( "Couldn't update dashboard #" . $attr->Id . ":$msg" ) unless $ret;
}
}
}
},
sub {
my $attrs = RT::Attributes->new( RT->SystemUser );
$attrs->Limit( FIELD => 'Name', VALUE => [ 'Dashboard', 'SelfServiceDashboard' ], OPERATOR => 'IN' );
while ( my $attr = $attrs->Next ) {
my $content = $attr->Content;
if ( $content && $content->{Panes} ) {
my $layout;
if ( $content->{Width} ) {
$layout = join ',', map {"col-md-$_"} map { $content->{Width}{$_} || () } qw/body sidebar/;
}
$layout ||= 'col-md-8,col-md-4';

my @cols;
for my $pane ( sort keys %{ $content->{Panes} } ) {
my @elements;
for my $portlet ( @{ $content->{Panes}->{$pane} } ) {
delete $portlet->{pane};
$portlet->{description} =~ s!^Saved Search:!Ticket:!;
push @elements, $portlet;
}
push @cols, \@elements;
}
my ( $ret, $msg ) = $attr->SetContent(
{
Elements => [
{
Layout => $layout,
Elements => \@cols,
}
]
}
);
RT->Logger->error( "Couldn't update dashboard #" . $attr->Id . ":$msg" ) unless $ret;
}
}
},
);
62 changes: 28 additions & 34 deletions lib/RT/Attribute.pm
Original file line number Diff line number Diff line change
Expand Up @@ -844,14 +844,11 @@ sub FindDependencies {
}
# dashboards have dependencies on all the searches and dashboards they use
elsif ($self->Name eq 'Dashboard' || $self->Name eq 'SelfServiceDashboard') {
my $content = $self->Content;
for my $pane (values %{ $content->{Panes} || {} }) {
for my $component (@$pane) {
if ($component->{portlet_type} eq 'search' || $component->{portlet_type} eq 'dashboard') {
my $attr = RT::Attribute->new($self->CurrentUser);
$attr->LoadById($component->{id});
$deps->Add( out => $attr );
}
for my $component ( RT::Dashboard->Portlets( $self->Content->{Elements} || [] ) ) {
if ( $component->{portlet_type} eq 'search' || $component->{portlet_type} eq 'dashboard' ) {
my $attr = RT::Attribute->new( $self->CurrentUser );
$attr->LoadById( $component->{id} );
$deps->Add( out => $attr );
}
}
}
Expand Down Expand Up @@ -1013,25 +1010,24 @@ sub PostInflateFixup {
elsif ($self->Name eq 'Dashboard') {
my $content = $self->Content;

for my $pane (values %{ $content->{Panes} || {} }) {
for (@$pane) {
if (ref($_->{uid}) eq 'SCALAR') {
my $uid = $_->{uid};
my $attr = $importer->LookupObj($$uid);
for ( RT::Dashboard->Portlets( $content->{Elements} || [] ) ) {
if ( ref( $_->{uid} ) eq 'SCALAR' ) {
my $uid = $_->{uid};
my $attr = $importer->LookupObj($$uid);

if ($attr) {
# update with the new id numbers assigned to us
$_->{id} = $attr->Id;
$_->{privacy} = join '-', $attr->ObjectType, $attr->ObjectId;
delete $_->{uid};
}
else {
$importer->Postpone(
for => $$uid,
uid => $spec->{uid},
method => 'PostInflateFixup',
);
}
if ($attr) {

# update with the new id numbers assigned to us
$_->{id} = $attr->Id;
$_->{privacy} = join '-', $attr->ObjectType, $attr->ObjectId;
delete $_->{uid};
}
else {
$importer->Postpone(
for => $$uid,
uid => $spec->{uid},
method => 'PostInflateFixup',
);
}
}
}
Expand Down Expand Up @@ -1115,13 +1111,11 @@ sub Serialize {
# encode saved searches and dashboards to be UIDs
elsif ($store{Name} eq 'Dashboard') {
my $content = $self->_DeserializeContent($store{Content}) || {};
for my $pane (values %{ $content->{Panes} || {} }) {
for (@$pane) {
if ($_->{portlet_type} eq 'search' || $_->{portlet_type} eq 'dashboard') {
$_->{uid} = \( join '-', 'RT::Attribute', $RT::Organization, $_->{id} );
}
# pass through everything else (e.g. component)
for ( RT::Dashboard->Portlets( $content->{Elements} || [] ) ) {
if ($_->{portlet_type} eq 'search' || $_->{portlet_type} eq 'dashboard') {
$_->{uid} = \( join '-', 'RT::Attribute', $RT::Organization, $_->{id} );
}
# pass through everything else (e.g. component)
}
$store{Content} = $self->_SerializeContent($content);
}
Expand Down Expand Up @@ -1189,8 +1183,8 @@ sub _SyncLinks {
if ( $name eq 'Dashboard' ) {
my $content = $self->_DeserializeContent( $self->__Value('Content') );

my %searches = map { $_->{id} => 1 } grep { $_->{portlet_type} eq 'search' } @{ $content->{Panes}{body} },
@{ $content->{Panes}{sidebar} };
my %searches = map { $_->{id} => 1 }
grep { $_->{portlet_type} eq 'search' } RT::Dashboard->Portlets( $content->{Elements} || [] );

my $links = $self->DependsOn;
while ( my $link = $links->Next ) {
Expand Down
4 changes: 2 additions & 2 deletions lib/RT/Config.pm
Original file line number Diff line number Diff line change
Expand Up @@ -452,9 +452,9 @@ our %META;
},
},

# User overridable options for RT at a glance
# User overridable options for Homepage
HomePageRefreshInterval => {
Section => 'RT at a glance', #loc
Section => 'Homepage', #loc
Overridable => 1,
SortOrder => 2,
Widget => '/Widgets/Form/Select',
Expand Down
Loading

0 comments on commit cd5e7b4

Please sign in to comment.