From c9548a5bef884f1f4fd06585ca724220f0283a8e Mon Sep 17 00:00:00 2001 From: sunnavy Date: Tue, 2 Jul 2024 16:58:31 -0400 Subject: [PATCH] Support lazy load for widgets --- lib/RT/Interface/Web.pm | 3 +++ share/html/Elements/DropdownMenu | 2 +- share/html/Elements/ShowWidgets | 14 ++++++++++--- share/html/Ticket/Display.html | 12 +---------- share/html/Ticket/Elements/ShowSummary | 21 +------------------ share/html/Ticket/Widgets/Basics | 12 ++++++++--- .../Ticket/Widgets/CustomFieldCustomGroupings | 9 ++++++-- share/html/Ticket/Widgets/Dates | 10 ++++++--- share/html/Ticket/Widgets/Links | 9 ++++---- share/html/Ticket/Widgets/People | 12 ++++++++--- share/html/Ticket/Widgets/Summary | 2 +- share/html/Views/Ticket/dhandler | 11 ++++++++-- share/html/Widgets/TitleBox | 5 ++--- 13 files changed, 66 insertions(+), 56 deletions(-) diff --git a/lib/RT/Interface/Web.pm b/lib/RT/Interface/Web.pm index 9f9aec0f35..fe2845e720 100644 --- a/lib/RT/Interface/Web.pm +++ b/lib/RT/Interface/Web.pm @@ -1344,6 +1344,9 @@ if ((RequestENV('HTTP_USER_AGENT') || '') =~ /(?:hiptop|Blazer|Novarra|Vagabond| } +sub ModernClient { + return ( RequestENV('HTTP_USER_AGENT') // '' ) =~ /WWW-Mechanize/ ? 0 : 1; +} sub StripContent { my %args = @_; diff --git a/share/html/Elements/DropdownMenu b/share/html/Elements/DropdownMenu index 72298ca642..21e3d4c4db 100644 --- a/share/html/Elements/DropdownMenu +++ b/share/html/Elements/DropdownMenu @@ -61,7 +61,7 @@ % if ( $item eq 'HideUnsetFields' ) { % my $show_label = loc("Show unset fields"); % my $hide_label = loc("Hide unset fields"); -% my $initial_label = $ARGS{HideUnsetFields} ? $show_label : $hide_label; +% my $initial_label = $ARGS{HideUnsetFields} // $DECODED_ARGS->{HideUnsetFields} ? $show_label : $hide_label; diff --git a/share/html/Elements/ShowWidgets b/share/html/Elements/ShowWidgets index 66ca45ea23..4f0247a592 100644 --- a/share/html/Elements/ShowWidgets +++ b/share/html/Elements/ShowWidgets @@ -63,9 +63,15 @@ % else { % $path = $widget; % } -% $path = '/Ticket/Widgets/' . $path unless $path =~ m{^/}; +% $path = $path_prefix . $path; % if ( $m->comp_exists( $path ) ) { - <& $path, %$ARGSRef, ref $widget ? ( WidgetConfig => $widget ) : () &> +% # Disable lazy load for wrapper widgets like "Summary" or mechanize tests +% if ( ref $widget || !RT::Interface::Web->ModernClient() ) { + <& $path, ref $widget ? ( WidgetConfig => $widget ) : (), $Object->isa('RT::Ticket') ? ( Ticket => $Object ) : ( Object => $Object ) &> +% } else { + <& /Widgets/HTMXLoadStart, htmx_get => "/Views$path?id=" . $Object->Id, lazy_load => 1 &> + <& /Widgets/HTMXLoadEnd &> +% } % } else { % RT->Logger->warning("Could not find $path"); % } @@ -93,12 +99,14 @@ for my $item ( split /\s*,\s*/, $Layout // '' ) { RT->Logger->warning("Unsupported layout item '$item'"); } } + +my $path_prefix = $Object->isa('RT::Ticket') ? '/Ticket/Widgets/' : ''; <%ARGS> -$ARGSRef => {} $Content => undef $Layout => undef $InRow => undef $ExtraColumnClass => undef +$Object => '' diff --git a/share/html/Ticket/Display.html b/share/html/Ticket/Display.html index 6869096dd1..3a66ed7126 100644 --- a/share/html/Ticket/Display.html +++ b/share/html/Ticket/Display.html @@ -60,8 +60,7 @@ <& Elements/ShowDependencyStatus, Ticket => $TicketObj &> - -<& /Elements/ShowWidgets, Content => $content, Layout => $layout, InRow => 0, ARGSRef => { %ARGS, Ticket => $TicketObj, Transactions => $transactions, Attachments => $attachments, InlineEdit => $InlineEdit } &> +<& /Elements/ShowWidgets, Content => $content, Layout => $layout, InRow => 0, Object => $TicketObj &> <%ARGS> $TicketObj => undef @@ -226,15 +225,6 @@ Arguments => { id => $TicketObj->id, exists $ARGS{ShowHistory} ? ( ShowHistory => $ARGS{ShowHistory} ) : () }, ); -my $transactions; -if ( $ARGS{'ReverseTxns'} ) { - $transactions = $TicketObj->SortedTransactions($ARGS{'ReverseTxns'}); -} -else { - $transactions = $TicketObj->SortedTransactions; -} -my $attachments = $TicketObj->Attachments; - my %link_rel; if (RT::Config->Get( 'ShowSearchNavigation', $session{'CurrentUser'} ) && defined $session{'collection-RT::Tickets'} and ($ARGS{'Query'} or $session{'CurrentSearchHash'}->{'Query'})) { my $item_map = $session{'collection-RT::Tickets'}->ItemMap; diff --git a/share/html/Ticket/Elements/ShowSummary b/share/html/Ticket/Elements/ShowSummary index f3ae70f3bd..f74d975812 100644 --- a/share/html/Ticket/Elements/ShowSummary +++ b/share/html/Ticket/Elements/ShowSummary @@ -52,30 +52,11 @@ Layout => $Layout, ExtraColumnClass => 'boxcontainer', InRow => 1, - ARGSRef => { - %ARGS, - CanModify => $can_modify, - CanModifyCF => $can_modify_cf, - CanModifyOwner => $can_modify_owner, - CanModifyPeople => $can_modify_people, - }, + Object => $Ticket, &> <%ARGS> $Ticket => undef -$Attachments => undef -$InlineEdit => 0 $Content => undef $Layout => 'col-md-6' -<%INIT> -my $can_modify = $Ticket->CurrentUserHasRight('ModifyTicket'); -my $can_modify_cf = $Ticket->CurrentUserHasRight('ModifyCustomField'); -my ($can_modify_owner) = $Ticket->CurrentUserCanSetOwner(); -my $can_modify_people = $Ticket->CurrentUserHasRight('Watch') - || $Ticket->CurrentUserHasRight('WatchAsAdminCc'); - -$m->callback( CallbackName => 'ModifyRights', %ARGS, TicketObj => $Ticket, ARGSRef => \%ARGS, - CanModify => \$can_modify, CanModifyCF => \$can_modify_cf, - CanModifyOwner => \$can_modify_owner, CanModifyPeople => \$can_modify_people ); - diff --git a/share/html/Ticket/Widgets/Basics b/share/html/Ticket/Widgets/Basics index 2b9dacbc12..328a2938d7 100644 --- a/share/html/Ticket/Widgets/Basics +++ b/share/html/Ticket/Widgets/Basics @@ -48,8 +48,8 @@ % $m->callback( %ARGS, CallbackName => 'BeforeBasics' ); <&| /Widgets/TitleBox, title => loc('The Basics'), - (($ARGS{CanModify} || $ARGS{CanModifyCF}) ? (title_href => RT->Config->Get('WebPath')."/Ticket/Modify.html?id=".$Ticket->Id) : ()), - (($ARGS{CanModify} || $ARGS{CanModifyCF}) && $modify_behavior =~ /^(link|click)$/ ? (titleright_raw => $m->scomp('/Elements/InlineEditLink')) : ()), + (($can_modify || $can_modify_cf) ? (title_href => RT->Config->Get('WebPath')."/Ticket/Modify.html?id=".$Ticket->Id) : ()), + (($can_modify || $can_modify_cf) && $modify_behavior =~ /^(link|click)$/ ? (titleright_raw => $m->scomp('/Elements/InlineEditLink')) : ()), class => (join " ", 'ticket-info-basics', ($modify_behavior eq 'always' ? 'editing' : ())), data => { 'inline-edit-behavior' => $modify_behavior }, &> @@ -80,7 +80,13 @@ my %inline_edit_behavior; if ( RT->Config->Get('InlineEditPanelBehavior') ) { %inline_edit_behavior = %{ RT->Config->Get('InlineEditPanelBehavior')->{'RT::Ticket'} || {} }; } -my $modify_behavior = $ARGS{InlineEdit} ? ($inline_edit_behavior{Basics} || $inline_edit_behavior{_default} || 'link') : 'hide'; +my $modify_behavior + = RT->Config->Get( 'InlineEdit', $session{CurrentUser} ) + ? ( $inline_edit_behavior{Basics} || $inline_edit_behavior{_default} || 'link' ) + : 'hide'; + +my $can_modify = $Ticket->CurrentUserHasRight('ModifyTicket'); +my $can_modify_cf = $Ticket->CurrentUserHasRight('ModifyCustomField'); <%ARGS> $Ticket diff --git a/share/html/Ticket/Widgets/CustomFieldCustomGroupings b/share/html/Ticket/Widgets/CustomFieldCustomGroupings index 1d1d2a74b3..e259e78008 100644 --- a/share/html/Ticket/Widgets/CustomFieldCustomGroupings +++ b/share/html/Ticket/Widgets/CustomFieldCustomGroupings @@ -49,12 +49,17 @@ <& /Elements/ShowCustomFieldCustomGroupings, Object => $Ticket, - title_href => ($ARGS{CanModify} || $ARGS{CanModifyCF}) ? RT->Config->Get('WebPath')."/Ticket/Modify.html" : "", - InlineEdit => ($ARGS{CanModify} || $ARGS{CanModifyCF}) ? $ARGS{InlineEdit} : 0, + title_href => ( $can_modify || $can_modify_cf ) ? RT->Config->Get('WebPath') . "/Ticket/Modify.html" : "", + InlineEdit => ( $can_modify || $can_modify_cf ) ? RT->Config->Get( 'InlineEdit', $session{CurrentUser} ) : 0, &> % $m->callback( %ARGS, CallbackName => 'AfterCustomFields' ); +<%INIT> +my $can_modify = $Ticket->CurrentUserHasRight('ModifyTicket'); +my $can_modify_cf = $Ticket->CurrentUserHasRight('ModifyCustomField'); + + <%ARGS> $Ticket diff --git a/share/html/Ticket/Widgets/Dates b/share/html/Ticket/Widgets/Dates index 6ab906de4d..59bf76429f 100644 --- a/share/html/Ticket/Widgets/Dates +++ b/share/html/Ticket/Widgets/Dates @@ -48,9 +48,9 @@ % $m->callback( %ARGS, CallbackName => 'BeforeDates' ); <&| /Widgets/TitleBox, title => loc("Dates"), - ($ARGS{CanModify} ? (title_href => RT->Config->Get('WebPath')."/Ticket/ModifyDates.html?id=".$Ticket->Id) : ()), + ($can_modify ? (title_href => RT->Config->Get('WebPath')."/Ticket/ModifyDates.html?id=".$Ticket->Id) : ()), class => (join " ", 'ticket-info-dates', ($modify_behavior eq 'always' ? 'editing' : ())), - ($ARGS{CanModify} && $modify_behavior =~ /^(link|click)$/ ? (titleright_raw => $m->scomp('/Elements/InlineEditLink')) : ()), + ($can_modify && $modify_behavior =~ /^(link|click)$/ ? (titleright_raw => $m->scomp('/Elements/InlineEditLink')) : ()), data => { 'inline-edit-behavior' => $modify_behavior }, &> % unless ($modify_behavior eq 'always') { @@ -80,7 +80,11 @@ if ( RT->Config->Get('InlineEditPanelBehavior') ) { %inline_edit_behavior = %{ RT->Config->Get('InlineEditPanelBehavior')->{'RT::Ticket'} || {} }; } my $modify_behavior - = $ARGS{InlineEdit} ? ( $inline_edit_behavior{Dates} || $inline_edit_behavior{_default} || 'link' ) : 'hide'; + = RT->Config->Get( 'InlineEdit', $session{CurrentUser} ) + ? ( $inline_edit_behavior{Dates} || $inline_edit_behavior{_default} || 'link' ) + : 'hide'; + +my $can_modify = $Ticket->CurrentUserHasRight('ModifyTicket'); <%ARGS> diff --git a/share/html/Ticket/Widgets/Links b/share/html/Ticket/Widgets/Links index d6ef0747fc..b60aa1800b 100644 --- a/share/html/Ticket/Widgets/Links +++ b/share/html/Ticket/Widgets/Links @@ -49,10 +49,10 @@ % $m->callback( %ARGS, CallbackName => 'LinksExtra', extra => \@extra ); <&| /Widgets/TitleBox, title => loc('Links'), - ($ARGS{CanModify} ? (title_href => RT->Config->Get('WebPath')."/Ticket/ModifyLinks.html?id=".$Ticket->Id) : ()), + ($can_modify ? (title_href => RT->Config->Get('WebPath')."/Ticket/ModifyLinks.html?id=".$Ticket->Id) : ()), class => (join " ", 'ticket-info-links', ($modify_behavior eq 'always' ? 'editing' : ())), data => { 'inline-edit-behavior' => $modify_behavior }, - ($ARGS{CanModify} ? (title_href => RT->Config->Get('WebPath')."/Ticket/ModifyLinks.html?id=".$Ticket->Id) : ()), + ($can_modify ? (title_href => RT->Config->Get('WebPath')."/Ticket/ModifyLinks.html?id=".$Ticket->Id) : ()), @extra, &> % unless ($modify_behavior eq 'always') { @@ -87,14 +87,15 @@ if ( RT->Config->Get('InlineEditPanelBehavior') ) { %inline_edit_behavior = %{ RT->Config->Get('InlineEditPanelBehavior')->{'RT::Ticket'} || {} }; } my $modify_behavior - = $ARGS{InlineEdit} ? ( $inline_edit_behavior{Links} || $inline_edit_behavior{_default} || 'link' ) : 'hide'; + = RT->Config->Get( 'InlineEdit', $session{CurrentUser} ) ? ( $inline_edit_behavior{Links} || $inline_edit_behavior{_default} || 'link' ) : 'hide'; +my $can_modify = $Ticket->CurrentUserHasRight('ModifyTicket'); my @extra; my $alt = loc('Graph ticket links'); my $links_graph = ''; my $links_titleright = join ' ', - ($ARGS{CanModify} && $modify_behavior =~ /^(link|click)$/ ? ($m->scomp('/Elements/InlineEditLink')) : ()), + ($can_modify && $modify_behavior =~ /^(link|click)$/ ? ($m->scomp('/Elements/InlineEditLink')) : ()), (RT->Config->Get('DisableGraphViz') ? () : $links_graph); push @extra, (titleright_raw => $links_titleright) if $links_titleright; diff --git a/share/html/Ticket/Widgets/People b/share/html/Ticket/Widgets/People index 0724b87813..68aa512fea 100644 --- a/share/html/Ticket/Widgets/People +++ b/share/html/Ticket/Widgets/People @@ -48,9 +48,9 @@ % $m->callback( %ARGS, CallbackName => 'BeforePeople' ); <&| /Widgets/TitleBox, title => loc('People'), - (($ARGS{CanModify} || $ARGS{CanModifyOwner} || $ARGS{CanModifyPeople}) ? (title_href => RT->Config->Get('WebPath')."/Ticket/ModifyPeople.html?id=".$Ticket->Id) : ()), + (($can_modify || $can_modify_owner || $can_modify_people) ? (title_href => RT->Config->Get('WebPath')."/Ticket/ModifyPeople.html?id=".$Ticket->Id) : ()), class => (join " ", 'ticket-info-people', ($modify_behavior eq 'always' ? 'editing' : ())), - (($ARGS{CanModify} || $ARGS{CanModifyOwner} || $ARGS{CanModifyPeople}) && $modify_behavior =~ /^(link|click)$/ ? (titleright_raw => $m->scomp('/Elements/InlineEditLink')) : ()), + (($can_modify || $can_modify_owner || $can_modify_people) && $modify_behavior =~ /^(link|click)$/ ? (titleright_raw => $m->scomp('/Elements/InlineEditLink')) : ()), data => { 'inline-edit-behavior' => $modify_behavior }, &> % unless ($modify_behavior eq 'always') { @@ -81,7 +81,13 @@ if ( RT->Config->Get('InlineEditPanelBehavior') ) { %inline_edit_behavior = %{ RT->Config->Get('InlineEditPanelBehavior')->{'RT::Ticket'} || {} }; } my $modify_behavior - = $ARGS{InlineEdit} ? ( $inline_edit_behavior{People} || $inline_edit_behavior{_default} || 'link' ) : 'hide'; + = RT->Config->Get( 'InlineEdit', $session{CurrentUser} ) + ? ( $inline_edit_behavior{People} || $inline_edit_behavior{_default} || 'link' ) + : 'hide'; + +my $can_modify = $Ticket->CurrentUserHasRight('ModifyTicket'); +my ($can_modify_owner) = $Ticket->CurrentUserCanSetOwner(); +my $can_modify_people = $Ticket->CurrentUserHasRight('Watch') || $Ticket->CurrentUserHasRight('WatchAsAdminCc'); <%ARGS> $Ticket diff --git a/share/html/Ticket/Widgets/Summary b/share/html/Ticket/Widgets/Summary index 81e86d4cf6..f17637399a 100644 --- a/share/html/Ticket/Widgets/Summary +++ b/share/html/Ticket/Widgets/Summary @@ -46,7 +46,7 @@ %# %# END BPS TAGGED BLOCK }}} % $m->callback( %ARGS, CallbackName => 'BeforeShowSummary' ); -
+
<&| /Widgets/TitleBox, title => loc('Ticket metadata'), titleright_raw => $m->scomp('/Elements/DropdownMenu', %ARGS), class => 'fullwidth' &> <& /Ticket/Elements/ShowSummary, %ARGS, ref $WidgetConfig ? %$WidgetConfig : () &> diff --git a/share/html/Views/Ticket/dhandler b/share/html/Views/Ticket/dhandler index 453beed19d..078d414b82 100644 --- a/share/html/Views/Ticket/dhandler +++ b/share/html/Views/Ticket/dhandler @@ -56,13 +56,20 @@ unless ( $ticket->CurrentUserCanSee ) { Abort( loc('Permission Denied'), SuppressHeader => 1, Code => HTTP::Status::HTTP_FORBIDDEN ); } -unless ( $m->comp_exists("/Ticket/Elements/$component_name") ) { +my $path; +if ( $m->comp_exists("/Ticket/$component_name") ) { + $path = "/Ticket/$component_name"; +} +elsif ( $m->comp_exists("/Ticket/Elements/$component_name") ) { + $path = "/Ticket/Elements/$component_name"; +} +else { RT->Logger->warning( "Component $component_name does not exist" ); Abort( loc('Invalid Path'), SuppressHeader => 1 ); } my $out; -eval { $out = $m->scomp( "/Ticket/Elements/$component_name", Ticket => $ticket, TicketObj => $ticket, %ARGS ) }; +eval { $out = $m->scomp( $path, Ticket => $ticket, TicketObj => $ticket, %ARGS ) }; if ($@) { RT->Logger->warning("Error loading $component_name: $@"); Abort( loc('Error'), SuppressHeader => 1 ); diff --git a/share/html/Widgets/TitleBox b/share/html/Widgets/TitleBox index 04a35a8b52..fa9ea23628 100644 --- a/share/html/Widgets/TitleBox +++ b/share/html/Widgets/TitleBox @@ -91,7 +91,7 @@ $htmx_get => undef my $content; # If htmx_load is set to 0 explicitly, render with titlebox even for /Views/ -if ( $m->request_path =~ /^\/Views/ && ( $htmx_load // 1 ) ) { +if ( $m->request_path =~ /^\/Views/ && $m->request_path !~ m{/Widgets/} && ( $htmx_load // 1 ) ) { # HTMX load, send content with no titlebox $m->out( $m->content ); @@ -103,8 +103,7 @@ elsif ( my $name = $m->notes('HTMXLoadComponent') ) { $htmx_get = RT->Config->Get('WebPath') . '/Views/Component/' . $name . '?From=' . RT->Config->Get('WebPath') . $m->request_path; } -$content = $m->content - unless $htmx_load && ( RT::Interface::Web::RequestENV('HTTP_USER_AGENT') // '' ) !~ /WWW-Mechanize/; +$content = $m->content unless $htmx_load && RT::Interface::Web->ModernClient(); $m->callback( CallbackName => "ModifyContent", ARGSRef => \%ARGS, Content => \$content, Class => \$class, HideEmpty => \$hide_empty, HideChrome => \$hide_chrome );