Skip to content

Commit 0975b82

Browse files
author
Torsten Brumm
committed
Bring back this Extension and port to rt6
Ported to RT6 with some new features
1 parent 4ac7dab commit 0975b82

12 files changed

Lines changed: 373 additions & 92 deletions

File tree

MANIFEST

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
11
Changes
2+
doc/screenshot-menu-button.png
3+
doc/screenshot-preferences.png
4+
README.md
5+
html/Callbacks/SideBySideView/Elements/Tabs/Privileged
6+
html/Callbacks/SideBySideView/Ticket/Display.html/BeforeActionList
27
html/Callbacks/SideBySideView/Ticket/Display.html/BeforeShowSummary
8+
html/SideBySideView/SetLayout.html
9+
html/Ticket/Elements/SideBySideViewToggle
310
inc/Module/Install.pm
411
inc/Module/Install/Base.pm
512
inc/Module/Install/Can.pm
@@ -15,6 +22,7 @@ inc/Module/Install/Win32.pm
1522
inc/Module/Install/WriteAll.pm
1623
inc/YAML/Tiny.pm
1724
lib/RT/Extension/SideBySideView.pm
25+
lib/RT/Interface/Web_Overlay.pm
1826
Makefile.PL
1927
MANIFEST This list of files
2028
MANIFEST.SKIP

Makefile.PL

Lines changed: 7 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,9 @@
11
use inc::Module::Install;
22

3-
RTx 'RT-Extension-SideBySideView';
4-
repository 'https://github.com/tbrumm/RT-Extension-SideBySideView';
5-
6-
# this is only because M::I author_from doesn't support multiple authors
7-
author 'Christian Loos <cloos@netsandbox.de>';
8-
9-
requires_rt '4.0.0';
10-
rt_too_new '5.2.0';
11-
12-
substitute(
13-
{ RT_LIB_PATH => "$RT::LocalPath/lib " . File::Basename::dirname( $INC{'RT.pm'} ) },
14-
{ sufix => '.in' },
15-
'xt/lib/RT/Extension/SideBySideView/Test.pm',
16-
);
17-
18-
sign;
19-
WriteAll;
3+
RTx('RT-Extension-SideBySideView');
4+
license('gpl_2');
5+
author('Torsten Brumm <technik@picturepunxx.de>');
6+
version_from('lib/RT/Extension/SideBySideView.pm');
7+
requires_rt('6.0.0');
8+
rt_too_new('7.0.0');
9+
WriteAll();

README.md

Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
# RT::Extension::SideBySideView
2+
3+
Switchable ticket display layouts for **Request Tracker 6**.
4+
5+
Users can choose between two named page layouts — both via their personal
6+
preferences and via a one-click toggle button directly in the ticket menu bar.
7+
No administrator involvement is required after installation.
8+
9+
---
10+
11+
## What it does
12+
13+
RT 6 renders ticket detail pages using a configurable *PageLayout* system.
14+
This extension registers two alternative layouts and lets each user switch
15+
between them independently:
16+
17+
- **Default View** — the familiar two-column metadata panel above a
18+
full-width Description + History section.
19+
- **Side-by-Side View** — a narrow metadata column (≈25 % width) placed
20+
permanently beside a wide History column (≈75 % width), so you can read
21+
the thread and check ticket details at the same time without scrolling back
22+
and forth.
23+
24+
Users who have not set a preference continue to see RT's built-in default
25+
layout unchanged — the extension is fully opt-in.
26+
27+
---
28+
29+
## Screenshots
30+
31+
### Layout toggle in the ticket menu bar
32+
33+
A `layout-split` icon button is added to the ticket menu bar next to the
34+
Bookmark (🔖) and Timer (🕐) buttons. One click switches the layout and
35+
reloads the ticket.
36+
37+
![Layout toggle button in the ticket menu bar](doc/screenshot-menu-button.png)
38+
39+
### User Preferences
40+
41+
The chosen layout is also available as a persistent per-user setting under
42+
*Preferences → Ticket display → Ticket display layout*. Changes made via the
43+
toggle button are immediately reflected here, and vice versa.
44+
45+
![Ticket display layout preference dropdown](doc/screenshot-preferences.png)
46+
47+
---
48+
49+
## Layouts in detail
50+
51+
### Default View
52+
53+
Two equal columns for metadata, full-width sections below.
54+
55+
| Left column | Right column |
56+
|-------------|--------------|
57+
| Basics, Times, Custom Fields, People, Attachments, Requestors | Reminders, Articles, Dates, Linked Queues, Assets, Links |
58+
59+
Below (full width): **Description · History**
60+
61+
### Side-by-Side View
62+
63+
Narrow metadata column next to a wide transaction history.
64+
65+
| Metadata (col-md-3) | History (col-md-9) |
66+
|---------------------|---------------------|
67+
| Basics, People, Dates, Times, Attachments, Custom Fields, Links, Requestors, Articles, Assets | Full transaction history (all types) |
68+
69+
---
70+
71+
## How it works
72+
73+
RT 6 determines the layout of a ticket display page via
74+
`HTML::Mason::Commands::GetPageLayout`, which consults the global
75+
`%PageLayoutMapping` configuration. Because that mapping is global and cannot
76+
vary per user, this extension wraps `GetPageLayout` through RT's standard
77+
overlay mechanism (`lib/RT/Interface/Web_Overlay.pm`). The wrapper checks the
78+
current user's `TicketViewLayout` preference on every ticket display request
79+
and, when a preference is set, returns the matching layout data structure
80+
directly — bypassing the global mapping entirely for that user.
81+
82+
The preference itself is registered as an `Overridable` RT config option with
83+
a Select widget, so it appears automatically in the standard RT Preferences
84+
page under *Ticket display* without any additional template changes.
85+
86+
The toggle button is injected into the ticket menu bar via the
87+
`Elements/Tabs/Privileged` callback, using the same `raw_html` / `sort_order`
88+
pattern that RT core uses for Bookmark and Timer. Clicking it performs a GET
89+
request to a small helper page (`SideBySideView/SetLayout.html`) that writes
90+
the new value into the user's preferences and redirects back to the ticket,
91+
which then re-renders with the new layout.
92+
93+
| File | Role |
94+
|------|------|
95+
| `lib/RT/Extension/SideBySideView.pm` | Registers the `TicketViewLayout` preference meta, defines both layout data structures, and adds the `layout-split` SVG icon to RT's icon set. |
96+
| `lib/RT/Interface/Web_Overlay.pm` | Loaded by RT's overlay mechanism at startup. Wraps `GetPageLayout` to honour the per-user layout preference for ticket display pages. |
97+
| `html/Ticket/Elements/SideBySideViewToggle` | Renders the icon link in the menu bar. Reads the current preference and links to the opposite layout. |
98+
| `html/Callbacks/SideBySideView/Elements/Tabs/Privileged` | Adds the toggle element to the ticket page menu at `sort_order => 97` (before Bookmark at 98, Timer at 99). |
99+
| `html/SideBySideView/SetLayout.html` | GET endpoint: saves the chosen layout to user preferences and redirects back to the ticket. |
100+
101+
---
102+
103+
## Requirements
104+
105+
- Request Tracker **6.0.0** or later (< 7.0.0)
106+
- Perl 5.10.1 or later
107+
108+
---
109+
110+
## Installation
111+
112+
```bash
113+
perl Makefile.PL
114+
make
115+
sudo make install
116+
```
117+
118+
Add the plugin to `/opt/rt6/etc/RT_SiteConfig.pm` (or a file in
119+
`RT_SiteConfig.d/`):
120+
121+
```perl
122+
Plugin('RT::Extension::SideBySideView');
123+
```
124+
125+
Clear the Mason cache and restart the web server:
126+
127+
```bash
128+
sudo systemctl stop apache2
129+
sudo rm -rf /opt/rt6/var/mason_data/obj/*
130+
sudo systemctl start apache2
131+
```
132+
133+
---
134+
135+
## Upgrading from v2.x (RT 4 / RT 5)
136+
137+
The old extension injected a CSS/JavaScript side-by-side layout via a
138+
`BeforeShowSummary` Mason callback that no longer exists in RT 6.
139+
140+
Remove the old plugin directory before installing the new version:
141+
142+
```bash
143+
sudo rm -rf /opt/rt6/local/plugins/RT-Extension-SideBySideView/
144+
```
145+
146+
Then follow the installation steps above. Previously saved `SideBySideView`
147+
boolean preferences are ignored; users select their layout from the Preferences
148+
page once after upgrading.
149+
150+
---
151+
152+
## Author
153+
154+
Torsten Brumm &lt;technik@picturepunxx.de&gt;
155+
156+
## Licence
157+
158+
GPL version 2

doc/screenshot-menu-button.png

12.6 KB
Loading

doc/screenshot-preferences.png

42.2 KB
Loading
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<%INIT>
2+
my $page_menu = PageMenu();
3+
return unless $page_menu;
4+
5+
my $request_path = $HTML::Mason::Commands::r->path_info;
6+
return unless $request_path =~ m{^/Ticket/};
7+
8+
my ($id) = ( $DECODED_ARGS->{'id'} // '' ) =~ /^(\d+)$/;
9+
return unless $id;
10+
11+
$page_menu->child(
12+
'sbsview-toggle',
13+
raw_html => $m->scomp( '/Ticket/Elements/SideBySideViewToggle', id => $id ),
14+
sort_order => 97,
15+
);
16+
</%INIT>
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
<%doc>
2+
Layout toggle is now in the ticket page menu (Elements/Tabs/Privileged callback).
3+
</%doc>
Lines changed: 4 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,4 @@
1-
<script type="text/javascript">
2-
jQuery(function() {
3-
% if ($RT::MAJOR_VERSION >= 5) {
4-
jQuery("div.card-body > div.ticket-summary > div.boxcontainer > div:first-child").unwrap();
5-
jQuery("div.card-body > div.ticket-summary > div").wrapAll("<div class='boxcontainer col'></div>");
6-
jQuery("div#body > div.summary").css({float: "left", width: "30%"});
7-
jQuery("div#body > div.summary > div.fullwidth > div.titlebox").css({"margin-top": "0", "margin-right": "20px"});
8-
% } else {
9-
jQuery("table.ticket-summary td.boxcontainer > div:first-child").unwrap();
10-
jQuery("#body > div.summary, #body > div.summary ~ div").wrapAll("<table width='100%'><tr></tr></table>");
11-
jQuery("#body > div.summary ~ div").wrapAll("<td valign='top' class='boxcontainer'></td>");
12-
jQuery("div.summary").wrap("<td valign='top' class='boxcontainer' style='width: 30%;'></td>");
13-
% }
14-
});
15-
</script>
16-
<%init>
17-
return unless RT->Config->Get( 'SideBySideView', $session{'CurrentUser'} );
18-
</%init>
1+
<%doc>
2+
Deliberately empty: this callback name does not exist in RT 6.
3+
The layout switching is handled by BeforeActionList and Web_Overlay.pm.
4+
</%doc>

html/SideBySideView/SetLayout.html

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<%INIT>
2+
unless ( $session{'CurrentUser'} && $session{'CurrentUser'}->id ) {
3+
Abort( loc('Permission denied'), Code => HTTP::Status::HTTP_FORBIDDEN );
4+
}
5+
6+
my %valid = map { $_ => 1 } qw( DefaultView SideBySideView );
7+
my $layout = $ARGS{Layout} // '';
8+
unless ( $valid{$layout} ) {
9+
Abort( loc('Invalid layout name') );
10+
}
11+
12+
my $user = $session{'CurrentUser'}->UserObj;
13+
my $prefs = $user->Preferences( RT->System ) || {};
14+
$prefs->{TicketViewLayout} = $layout;
15+
my ( $ok, $msg ) = $user->SetPreferences( RT->System, $prefs );
16+
RT->Logger->warning("SideBySideView: SetPreferences failed: $msg") unless $ok;
17+
18+
my ($id) = ( $ARGS{id} // '' ) =~ /^(\d+)$/;
19+
my $url = RT->Config->Get('WebURL') . 'Ticket/Display.html';
20+
$url .= "?id=$id" if $id;
21+
RT::Interface::Web::Redirect($url);
22+
</%INIT>
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<%ARGS>
2+
$id
3+
</%ARGS>
4+
<%INIT>
5+
my $current = RT->Config->Get( 'TicketViewLayout', $session{'CurrentUser'} ) // '';
6+
my $is_sbs = $current eq 'SideBySideView';
7+
my $target = $is_sbs ? 'DefaultView' : 'SideBySideView';
8+
my $title = $is_sbs ? loc('Switch to Default View') : loc('Switch to Side-by-Side View');
9+
my $url = RT->Config->Get('WebPath')
10+
. '/SideBySideView/SetLayout.html?id=' . $id
11+
. '&Layout=' . $target;
12+
</%INIT>
13+
<a hx-boost="false" href="<% $url %>" class="menu-item nav-link btn">
14+
<% GetSVGImage( Name => 'layout-split', Title => $title ) |n %>
15+
</a>

0 commit comments

Comments
 (0)