summaryrefslogtreecommitdiff
path: root/rt/html
diff options
context:
space:
mode:
Diffstat (limited to 'rt/html')
-rw-r--r--rt/html/Admin/Elements/ModifyQueue78
-rw-r--r--rt/html/Admin/Elements/ModifyUser99
-rw-r--r--rt/html/Admin/Users/Prefs.html122
-rw-r--r--rt/html/Callbacks/ActivityReports/Elements/Tabs/Default7
-rw-r--r--rt/html/Callbacks/ActivityReports/NoAuth/webrt.css/Default71
-rw-r--r--rt/html/Callbacks/ActivityReports/Search/Results.html/SearchActions7
-rw-r--r--rt/html/Callbacks/RT-WebCronTool/Elements/Tabs/Default13
-rw-r--r--rt/html/Callbacks/kStatistics/Elements/Tabs/Default11
-rw-r--r--rt/html/Developer/CronTool/autohandler9
-rw-r--r--rt/html/Developer/CronTool/index.html116
-rw-r--r--rt/html/Elements/CollectionAsTable/Row18
-rw-r--r--rt/html/Elements/Footer49
-rw-r--r--rt/html/Elements/FreesideInvoiceSearch20
-rw-r--r--rt/html/Elements/FreesideNewCust3
-rw-r--r--rt/html/Elements/FreesideSearch11
-rw-r--r--rt/html/Elements/FreesideSvcSearch11
-rw-r--r--rt/html/Elements/Header140
-rw-r--r--rt/html/Elements/Menu128
-rw-r--r--rt/html/Elements/PageLayout222
-rw-r--r--rt/html/Elements/QuickCreate39
-rw-r--r--rt/html/Elements/ShadedBox33
-rw-r--r--rt/html/Elements/ShadedInputRow35
-rw-r--r--rt/html/Elements/ShadedRow31
-rw-r--r--rt/html/Elements/SimpleSearch19
-rw-r--r--rt/html/Elements/Tabs34
-rw-r--r--rt/html/Elements/TicketList52
-rw-r--r--rt/html/Elements/TitleBoxStart49
-rw-r--r--rt/html/Elements/ViewUser51
-rw-r--r--rt/html/NoAuth/images/back_home.gifbin330 -> 0 bytes
-rw-r--r--rt/html/NoAuth/images/head_requestracker.gifbin1233 -> 0 bytes
-rw-r--r--rt/html/NoAuth/images/rt.jpgbin917 -> 0 bytes
-rw-r--r--rt/html/NoAuth/images/small-logo.pngbin0 -> 4887 bytes
-rw-r--r--rt/html/NoAuth/images/spacer.gifbin43 -> 0 bytes
-rw-r--r--rt/html/NoAuth/images/squares_blue.gifbin219 -> 0 bytes
-rw-r--r--rt/html/NoAuth/webrt.css243
-rwxr-xr-xrt/html/RTx/Statistics/CallsMultiQueue/Elements/Chart39
-rwxr-xr-xrt/html/RTx/Statistics/CallsMultiQueue/index.html330
-rwxr-xr-xrt/html/RTx/Statistics/CallsQueueDay/Elements/Chart29
-rw-r--r--rt/html/RTx/Statistics/CallsQueueDay/Results.tsv191
-rwxr-xr-xrt/html/RTx/Statistics/CallsQueueDay/index.html275
-rwxr-xr-xrt/html/RTx/Statistics/DayOfWeek/Elements/Chart26
-rwxr-xr-xrt/html/RTx/Statistics/DayOfWeek/index.html155
-rwxr-xr-xrt/html/RTx/Statistics/DurationAsString18
-rw-r--r--rt/html/RTx/Statistics/Elements/CollectionAsTable/Header126
-rw-r--r--rt/html/RTx/Statistics/Elements/CollectionAsTable/ParseFormat (renamed from rt/html/Admin/Global/CustomField.html)103
-rw-r--r--rt/html/RTx/Statistics/Elements/CollectionAsTable/Row112
-rw-r--r--rt/html/RTx/Statistics/Elements/ControlsAsTable/ControlBox103
-rw-r--r--rt/html/RTx/Statistics/Elements/ControlsAsTable/UpdatePage5
-rw-r--r--rt/html/RTx/Statistics/Elements/DateSelectRow55
-rwxr-xr-xrt/html/RTx/Statistics/Elements/DurationAsString18
-rw-r--r--rt/html/RTx/Statistics/Elements/GraphBox27
-rwxr-xr-x[-rw-r--r--]rt/html/RTx/Statistics/Elements/SelectMultiQueue (renamed from rt/html/Admin/Global/CustomFields.html)60
-rw-r--r--rt/html/RTx/Statistics/Elements/StatColumnMap173
-rwxr-xr-xrt/html/RTx/Statistics/Elements/Tabs72
-rw-r--r--rt/html/RTx/Statistics/FAQ/index.html23
-rwxr-xr-xrt/html/RTx/Statistics/OpenStalled/Elements/Chart27
-rw-r--r--rt/html/RTx/Statistics/OpenStalled/Results.tsv114
-rwxr-xr-xrt/html/RTx/Statistics/OpenStalled/index.html188
-rwxr-xr-xrt/html/RTx/Statistics/Resolution/Elements/Chart29
-rw-r--r--rt/html/RTx/Statistics/Resolution/index.html269
-rwxr-xr-xrt/html/RTx/Statistics/TimeToResolve/Elements/Chart23
-rwxr-xr-xrt/html/RTx/Statistics/TimeToResolve/index.html75
-rwxr-xr-xrt/html/RTx/Statistics/UserTest/Elements/Chart28
-rwxr-xr-xrt/html/RTx/Statistics/UserTest/index.html54
-rwxr-xr-xrt/html/RTx/Statistics/index.html59
-rw-r--r--rt/html/Reports/Activity/ActivityDetail.html83
-rw-r--r--rt/html/Reports/Activity/ActivitySummary.html61
-rw-r--r--rt/html/Reports/Activity/Elements/LimitReport23
-rw-r--r--rt/html/Reports/Activity/Elements/MiniPlot57
-rw-r--r--rt/html/Reports/Activity/Elements/PrintFooter7
-rw-r--r--rt/html/Reports/Activity/Elements/PrintHeader32
-rw-r--r--rt/html/Reports/Activity/Elements/ScreenFooter13
-rw-r--r--rt/html/Reports/Activity/Elements/ScreenHeader8
-rw-r--r--rt/html/Reports/Activity/Elements/Tabs52
-rw-r--r--rt/html/Reports/Activity/Elements/Wrapper16
-rw-r--r--rt/html/Reports/Activity/ResolutionComments.html62
-rw-r--r--rt/html/Reports/Activity/ResolutionStatistics.html95
-rw-r--r--rt/html/Reports/Activity/index.html29
-rw-r--r--rt/html/Search/Bulk.html482
-rw-r--r--rt/html/Search/Elements/PickRestriction142
-rw-r--r--rt/html/Search/Elements/TicketHeader40
-rw-r--r--rt/html/Search/Elements/TicketHeaderCell55
-rw-r--r--rt/html/Search/Elements/TicketRow55
-rw-r--r--rt/html/Search/Listing.html113
-rw-r--r--rt/html/Ticket/Elements/AddCustomers50
-rw-r--r--rt/html/Ticket/Elements/EditCustomers67
-rw-r--r--rt/html/Ticket/Elements/EditLinks133
-rw-r--r--rt/html/Ticket/Elements/ShowCustomers40
-rw-r--r--rt/html/Ticket/Elements/ShowLink40
-rw-r--r--rt/html/Ticket/Elements/ShowLinks87
-rw-r--r--rt/html/Ticket/Elements/ShowSummary98
-rw-r--r--rt/html/Ticket/Elements/Tabs96
-rw-r--r--rt/html/Ticket/ModifyCustomers.html49
93 files changed, 4549 insertions, 2063 deletions
diff --git a/rt/html/Admin/Elements/ModifyQueue b/rt/html/Admin/Elements/ModifyQueue
deleted file mode 100644
index 36f9ce17f..000000000
--- a/rt/html/Admin/Elements/ModifyQueue
+++ /dev/null
@@ -1,78 +0,0 @@
-%# BEGIN LICENSE BLOCK
-%#
-%# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com>
-%#
-%# (Except where explictly superceded by other copyright notices)
-%#
-%# 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.
-%#
-%# Unless otherwise specified, all modifications, corrections or
-%# extensions to this work which alter its source code become the
-%# property of Best Practical Solutions, LLC when submitted for
-%# inclusion in the work.
-%#
-%#
-%# END LICENSE BLOCK
-<& /Elements/TitleBoxStart, title => loc('Editing Configuration for queue [_1]', $QueueObj->Id) &>
-
-<FORM ACTION="<%$RT::WebPath%>/Admin/Queues/Modify.html" METHOD=POST>
-<INPUT TYPE=HIDDEN NAME=id VALUE="<%$QueueObj->Id%>">
-<TABLE>
-<TR><TD ALIGN=RIGHT>
-<&|/l&>Queue Name</&>:
-</TD>
-<TD><INPUT name="Name" value="<%$QueueObj->Name%>"></TD>
-</TR><TR>
-<TD ALIGN=RIGHT>
-<&|/l&>Description</&>:</TD><TD COLSPAN=3><INPUT name="Description" value="<%$QueueObj->Description%>" size=60></TD></TR>
-<TR>
-<TD ALIGN=RIGHT>
-<&|/l&>Correspondence Address</&>:
-</TD><TD>
-<INPUT name="CorrespondAddress" value="<%$QueueObj->CorrespondAddress%>">
-</TD>
-<TD ALIGN=RIGHT>
-
-<&|/l&>Comment Address</&>: </TD><TD>
-<INPUT NAME="CommentAddress" value="<%$QueueObj->CommentAddress%>">
-</TD>
-</TR><TR>
-
-<TD ALIGN=RIGHT>
-<&|/l&>Priority starts at</&>:
-</TD><TD><INPUT NAME="InitialPriority" value="<%$QueueObj->InitialPriority %>">
-</TD>
-<TD ALIGN=RIGHT>
-<&|/l&>Over time, priority moves toward</&>:
-</TD><TD><INPUT NAME="FinalPriority" value="<%$QueueObj->FinalPriority %>">
-</TD>
-</TR>
-<TR>
-<TD ALIGN=RIGHT>
-<&|/l&>Requests should be due in</&>:
-</TD><TD>
-<INPUT NAME="DefaultDueIn" VALUE="<%$QueueObj->DefaultDueIn%>"> <&|/l&>days</&>.
-</TD>
-</TR>
-</TABLE>
-<& /Elements/Submit, Label => loc('Save Changes') &>
-</form>
-<& /Elements/TitleBoxEnd &>
-
-<%INIT>
-
-</%INIT>
-
-<%ARGS>
-
-
-$QueueObj => undef
-</%ARGS>
diff --git a/rt/html/Admin/Elements/ModifyUser b/rt/html/Admin/Elements/ModifyUser
deleted file mode 100644
index 2faefefaa..000000000
--- a/rt/html/Admin/Elements/ModifyUser
+++ /dev/null
@@ -1,99 +0,0 @@
-%# BEGIN LICENSE BLOCK
-%#
-%# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com>
-%#
-%# (Except where explictly superceded by other copyright notices)
-%#
-%# 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.
-%#
-%# Unless otherwise specified, all modifications, corrections or
-%# extensions to this work which alter its source code become the
-%# property of Best Practical Solutions, LLC when submitted for
-%# inclusion in the work.
-%#
-%#
-%# END LICENSE BLOCK
-<& /Elements/TitleBoxStart, title => loc('Editing Configuration for user [_1]', $UserObj->Name) &>
-
-<FORM ACTION="<%$RT::WebPath%>/Admin/Users/Modify.html" METHOD=POST>
-<INPUT TYPE=HIDDEN NAME=id VALUE="<%$UserObj->Id%>">
-
-<&|/l&>Name</&>: <input name="Name" value="<%$UserObj->Name%>">
-<BR>
-<&|/l&>New Password</&>: <input type=password name="Pass1"><BR>
-<&|/l&>Retype Password</&>: <input type=password name="Pass2"><BR>
-
-<&|/l&>Comments</&>: <TEXTAREA name="Comments" COLS=80 ROWS=5 WRAP=VIRTUAL>
-<%$UserObj->Comments%></TEXTAREA>
-
-<BR>
-<&|/l&>Signature</&>: <TEXTAREA COLS=80 ROWS=5 name="Signature" WRAP=HARD>
-<%$UserObj->Signature%></TEXTAREA>
-<BR>
-<&|/l&>EmailAddress</&>: <input name="EmailAddress" value="<%$UserObj->EmailAddress%>">
-<BR>
-<&|/l&>FreeformContactInfo</&>: <input name="FreeformContactInfo" value="<%$UserObj->FreeformContactInfo%>">
-<BR>
-<&|/l&>Organization</&>: <input name="Organization" value="<%$UserObj->Organization%>">
-<BR>
-<&|/l&>RealName</&>: <input name="RealName" value="<%$UserObj->RealName%>">
-<BR>
-<&|/l&>NickName</&>: <input name="NickName" value="<%$UserObj->NickName%>">
-<BR>
-<&|/l&>Lang</&>: <input name="Lang" value="<%$UserObj->Lang%>">
-<BR>
-<&|/l&>EmailEncoding</&>: <input name="EmailEncoding" value="<%$UserObj->EmailEncoding%>">
-<BR>
-<&|/l&>WebEncoding</&>: <input name="WebEncoding" value="<%$UserObj->WebEncoding%>">
-<BR>
-<&|/l&>ExternalContactInfoId</&>: <input name="ExternalContactInfoId" value="<%$UserObj->ExternalContactInfoId%>">
-<BR>
-<&|/l&>ContactInfoSystem</&>: <input name="ContactInfoSystem" value="<%$UserObj->ContactInfoSystem%>">
-<BR>
-<&|/l&>UnixUsername</&>: <input name="Gecos" value="<%$UserObj->Gecos%>">
-<BR>
-<&|/l&>ExternalAuthId</&>: <input name="ExternalAuthId" value="<%$UserObj->ExternalAuthId%>">
-<BR>
-<&|/l&>AuthSystem</&>: <input name="AuthSystem" value="<%$UserObj->AuthSystem%>">
-<BR>
-<&|/l&>HomePhone</&>: <input name="HomePhone" value="<%$UserObj->HomePhone%>">
-<BR>
-<&|/l&>WorkPhone</&>: <input name="WorkPhone" value="<%$UserObj->WorkPhone%>">
-<BR>
-<&|/l&>MobilePhone</&>: <input name="MobilePhone" value="<%$UserObj->MobilePhone%>">
-<BR>
-<&|/l&>PagerPhone</&>: <input name="PagerPhone" value="<%$UserObj->PagerPhone%>">
-<BR>
-<&|/l&>Address1</&>: <input name="Address1" value="<%$UserObj->Address1%>">
-<BR>
-<&|/l&>Address2</&>: <input name="Address2" value="<%$UserObj->Address2%>">
-<BR>
-<&|/l&>City</&>: <input name="City" value="<%$UserObj->City%>">
-<BR>
-<&|/l&>State</&>: <input name="State" value="<%$UserObj->State%>">
-<BR>
-<&|/l&>Zip</&>: <input name="Zip" value="<%$UserObj->Zip%>">
-<BR>
-<&|/l&>Country</&>: <input name="Country" value="<%$UserObj->Country%>">
-<BR>
-<& /Elements/Submit, Label => loc('Save Changes') &>
-</form>
-<& /Elements/TitleBoxEnd &>
-
-<%INIT>
-
-</%INIT>
-
-<%ARGS>
-
-
-$UserObj => undef
-</%ARGS>
diff --git a/rt/html/Admin/Users/Prefs.html b/rt/html/Admin/Users/Prefs.html
deleted file mode 100644
index 0bba9fadd..000000000
--- a/rt/html/Admin/Users/Prefs.html
+++ /dev/null
@@ -1,122 +0,0 @@
-%# BEGIN LICENSE BLOCK
-%#
-%# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com>
-%#
-%# (Except where explictly superceded by other copyright notices)
-%#
-%# 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.
-%#
-%# Unless otherwise specified, all modifications, corrections or
-%# extensions to this work which alter its source code become the
-%# property of Best Practical Solutions, LLC when submitted for
-%# inclusion in the work.
-%#
-%#
-%# END LICENSE BLOCK
-<& /Elements/Header, Title => loc("User view") &>
-
-<& /Elements/ViewUser, User=>$u &>
-
-<h2 class="title"><%loc("User view")%></h2>
-
-%if ($session{CurrentUser} && ($session{CurrentUser}->Id == $id)) {
- <& /Elements/TitleBoxStart, title => loc('Signature') &>
-<form method=post>
-<input type="hidden" name="id" value=<%$id%>>
-<TEXTAREA COLS=72 ROWS=4 WRAP=HARD NAME="Signature"><% $u->Signature %></TEXTAREA><br><br>
-<input type="submit" value="<&|/l&>Update signature</&>">
-</form>
- <& /Elements/TitleBoxEnd &>
- <form method=post>
- <&|/l&>Open tickets (from listing) in another window</&>: <input type="checkbox" name="NewWindowOption" <%exists $session{NewWindowOption} && "CHECKED"%>><br>
- <&|/l&>Open tickets (from listing) in a new window</&>: <input type="checkbox" name="AlwaysNewWindowOption" <%exists $session{AlwaysNewWindowOption} && "CHECKED"%>><br>
- <input type="submit" name="NewWindowSetting" value="<&|/l&>New window setting</&>">
- </form>
-%}
-
- <& /Elements/TitleBoxStart, title => loc('Email') &>
-<form method=post>
-<input type="hidden" name="id" value="<%$id%>">
-<input name="Email" value="<% $u->EmailAddress %>"><input type="submit" value="<&|/l&>Update email</&>">
-</form>
- <& /Elements/TitleBoxEnd &>
- <& /Elements/TitleBoxStart, title => loc('Real Name') &>
-<form method=post>
-<input type="hidden" name="id" value="<%$id%>">
-<input name="RealName" value="<% $u->RealName %>"><input type="submit" value="<&|/l&>Update name</&>">
-</form>
- <& /Elements/TitleBoxEnd &>
-
- <& /Elements/TitleBoxStart, title => loc('User ID') &>
-<form method=post>
-<input type="hidden" name="id" value="<%$id%>">
-<input name="Name" value="<% $u->Name %>"><input type="submit" value="<&|/l&>Update ID</&>">
-</form>
- <& /Elements/TitleBoxEnd &>
-
-%# TODO: alternative email addresses + merging users
-
-<%ARGS>
-$id => $session{CurrentUser} ? $session{CurrentUser}->Id : 0
-$Signature => undef
-$Email => undef
-$RealName => undef
-$Name => undef
-</%ARGS>
-
-<%INIT>
-require RT::User;
-my $u=RT::User->new($session{CurrentUser});
-$u->Load($id) || die loc("Couldn't load that user ([_1])", $id);
-if ($Signature) {
-my ($val, $msg)=$u->SetSignature($Signature);
-$RT::Logger->log(level=>($val ? 'info' : 'error'), message=>$msg);
-}
-
-if ($Email) {
-my ($val, $msg)=$u->SetEmailAddress($Email);
-$RT::Logger->log(level=>($val ? 'info' : 'error'), message=>$msg);
-}
-
-if ($RealName) {
-my ($val, $msg)=$u->SetRealName($RealName);
-$RT::Logger->log(level=>($val ? 'info' : 'error'), message=>$msg);
-}
-
-if ($Name) {
-my ($val, $msg)=$u->SetName($Name);
-$RT::Logger->log(level=>($val ? 'info' : 'error'), message=>$msg);
-}
-
-if ($ARGS{NewWindowSetting}) {
-if ($ARGS{NewWindowOption}) {
-$session{NewWindowOption}=1;
-} else {
-delete $session{NewWindowOption};
-}
-if ($ARGS{AlwaysNewWindowOption}) {
-$session{NewWindowOption}=1;
-$session{AlwaysNewWindowOption}=1;
-} else {
-delete $session{AlwaysNewWindowOption};
-}
-}
-
-</%INIT>
-
-
-
-
-
-
-
-
-
diff --git a/rt/html/Callbacks/ActivityReports/Elements/Tabs/Default b/rt/html/Callbacks/ActivityReports/Elements/Tabs/Default
new file mode 100644
index 000000000..f85d2e010
--- /dev/null
+++ b/rt/html/Callbacks/ActivityReports/Elements/Tabs/Default
@@ -0,0 +1,7 @@
+<%init>
+if ($ARGS{current_toptab} eq "Tools/Offline.html") {
+ $ARGS{tabs}{r} ||= { path => 'Reports/Activity/index.html',
+ title => 'Reports',
+ };
+}
+</%init> \ No newline at end of file
diff --git a/rt/html/Callbacks/ActivityReports/NoAuth/webrt.css/Default b/rt/html/Callbacks/ActivityReports/NoAuth/webrt.css/Default
new file mode 100644
index 000000000..30480f7b6
--- /dev/null
+++ b/rt/html/Callbacks/ActivityReports/NoAuth/webrt.css/Default
@@ -0,0 +1,71 @@
+table.miniplot {
+ width: 100%;
+ border-collapse: collapse;
+}
+table.miniplot td {
+ margin: 0;
+ padding: 0;
+ border-bottom: 1px solid black;
+}
+table.miniplot .graph {
+ margin-left: auto;
+ margin-right: auto;
+ position: relative;
+ width: 60px;
+}
+table.miniplot .graph ul {
+ height: 100px;
+ margin: 0;
+ padding: 0;
+}
+table.miniplot .graph ul li {
+ list-style: none;
+ position: absolute;
+ bottom: 0px;
+ padding: 0 !important;
+ margin: 0 !important;
+ border-bottom: none;
+}
+table.miniplot .graph ul li .data {
+ display: none;
+}
+
+.miniplot .demoblock { margin: 0 10px; padding: 0 30px; }
+
+.miniplot .c1 { border: 2px solid #990000; background: #ff0000; }
+.miniplot .c2 { border: 2px solid #996600; background: #ff9900; }
+.miniplot .c3 { border: 2px solid #009900; background: #00ff00; }
+.miniplot .c4 { border: 2px solid #009999; background: #00ffff; }
+.miniplot .c5 { border: 2px solid #000099; background: #0000ff; }
+.miniplot .c6 { border: 2px solid #990099; background: #ff00ff; }
+graph .c5 { border: 2px solid #000099; background: #0000ff; }
+.graph .c6 { border: 2px solid #990099; background: #ff00ff; }
+
+tr.titlerow th {
+
+ border-bottom: solid black 1px;
+ margin: 0;
+ font-size:80%;
+ text-wrap: none;
+
+}
+
+tr.grandtotal td{
+ border-top: 1px solid black;
+}
+
+tr.grandtotal th{
+ border-top: 1px solid black;
+}
+
+th.label {
+ align: left;
+
+}
+
+table.miniplot th.legend {
+ font-style: normal;
+ font-size: 80%;
+
+}
+
diff --git a/rt/html/Callbacks/ActivityReports/Search/Results.html/SearchActions b/rt/html/Callbacks/ActivityReports/Search/Results.html/SearchActions
new file mode 100644
index 000000000..4775a9af3
--- /dev/null
+++ b/rt/html/Callbacks/ActivityReports/Search/Results.html/SearchActions
@@ -0,0 +1,7 @@
+<a href="<% $RT::WebPath %>/Reports/Activity/index.html?<% $QueryString %>">Generate reports</a>
+<%init>
+use YAML;
+my %args = $m->caller_args(2);
+
+my $QueryString = $m->comp('/Elements/QueryString', query => $args{Query});
+</%init> \ No newline at end of file
diff --git a/rt/html/Callbacks/RT-WebCronTool/Elements/Tabs/Default b/rt/html/Callbacks/RT-WebCronTool/Elements/Tabs/Default
new file mode 100644
index 000000000..db74ced2d
--- /dev/null
+++ b/rt/html/Callbacks/RT-WebCronTool/Elements/Tabs/Default
@@ -0,0 +1,13 @@
+%# The day after tomorrow is the third day of the rest of your life.
+<%INIT>
+if ($session{'CurrentUser'}->UserObj->HasRight(
+ Right => 'SuperUser',
+ Object => $RT::System,
+)) {
+ $toptabs->{'ZZ-RT-WebCronTool'} = { title =>loc("Web CronTool"),
+ path => "Developer/CronTool/index.html" };
+}
+</%init>
+<%args>
+$toptabs =>undef
+</%args>
diff --git a/rt/html/Callbacks/kStatistics/Elements/Tabs/Default b/rt/html/Callbacks/kStatistics/Elements/Tabs/Default
new file mode 100644
index 000000000..d4ca2b95e
--- /dev/null
+++ b/rt/html/Callbacks/kStatistics/Elements/Tabs/Default
@@ -0,0 +1,11 @@
+<%init>
+use RTx::Statistics;
+if (($Statistics::RestrictAccess == 0) || ($session{'CurrentUser'}->HasRight( Right => 'ShowConfigTab',
+ Object => $RT::System ))) {
+ $toptabs->{'ZZ-RTx-STATS'} = { title => 'RTx-Statistics',
+ path => "RTx/Statistics/index.html" };
+}
+</%init>
+<%args>
+ $toptabs =>undef
+</%args>
diff --git a/rt/html/Developer/CronTool/autohandler b/rt/html/Developer/CronTool/autohandler
new file mode 100644
index 000000000..7daa09e8d
--- /dev/null
+++ b/rt/html/Developer/CronTool/autohandler
@@ -0,0 +1,9 @@
+%# All theoretical chemistry is really physics;
+%# and all theoretical chemists know it.
+%# -- Richard P. Feynman
+<%INIT>
+$m->call_next(%ARGS) if $session{'CurrentUser'}->UserObj->HasRight(
+ Right => 'SuperUser',
+ Object => $RT::System,
+);
+</%INIT>
diff --git a/rt/html/Developer/CronTool/index.html b/rt/html/Developer/CronTool/index.html
new file mode 100644
index 000000000..67c9e5634
--- /dev/null
+++ b/rt/html/Developer/CronTool/index.html
@@ -0,0 +1,116 @@
+% if ($@) {
+<P><FONT Color="red"><% $@ %></FONT></P>
+% }
+% if (!$NoUI) {
+<HR>
+<FORM Action="index.html" Method="POST">
+<TABLE>
+% foreach my $class (qw( Search Condition Action )) {
+<TR><TH>
+<% loc($class) %>
+</TH><TD>
+<SELECT NAME="<% $class %>">
+% require File::Find;
+% my @modules;
+% File::Find::find(sub {
+% push @modules, $1 if /^(?!Generic|UserDefined)(\w+)\.pm$/i;
+% }, grep -d, map "$_/RT/$class", @INC);
+<OPTION <% $ARGS{$class} ? '' : 'SELECTED' %>></OPTION>
+% foreach my $module (sort @modules) {
+% my $fullname = "RT::$class\::$module";
+ <OPTION VALUE="<% $fullname %>" <% ($fullname eq $ARGS{$class}) ? 'SELECTED' : '' %>><% $module %></OPTION>
+% }
+</SELECT>
+</TD><TH>
+<&|/l&>Parameter</&>
+</TH><TD>
+<INPUT NAME="<% $class %>Arg" VALUE="<% $ARGS{$class.'Arg'} %>">
+</TD></TR>
+% }
+<TR>
+<TD COLSPAN="4" ALIGN="Right">
+<LABEL>
+<INPUT TYPE="CheckBox" NAME="Verbose" <% $Verbose ? 'CHECKED' : '' %>><&|/l&>Verbose</&>
+</LABEL>
+<INPUT TYPE="Submit" VALUE="<&|/l&>Run</&>">
+</TD>
+</TABLE>
+</FORM>
+<HR>
+% }
+<%INIT>
+$m->print("<H1>", loc("Web CronTool"), "</H1>");
+if ($Search) {
+ my $load_module = sub {
+ my $modname = $_[0];
+ $modname =~ s{::}{/}g;
+ require "$modname.pm" or die (
+ loc( "Failed to load module [_1]. ([_2])", $_[0], $@ ) . "\n"
+ );
+ };
+ $m->print(loc("Starting..."), "<UL>");
+ eval {
+ $load_module->($Search);
+ $load_module->($Action) if $Action;
+ $load_module->($Condition) if $Condition;
+
+ if ($TemplateId and !$TemplateObj) {
+ $TemplateObj = RT::Template->new($RT::Nobody);
+ $TemplateObj->LoadById($TemplateId);
+ }
+
+ my $tickets = RT::Tickets->new($RT::SystemUser);
+ my $search = $Search->new( TicketsObj => $tickets, Argument => $SearchArg );
+ $search->Prepare;
+ my $tickets_found = $search->TicketsObj;
+
+ #for each ticket we've found
+ while ( my $ticket = $tickets_found->Next ) {
+ $m->print("<LI>" . $ticket->Id . ": ") if $Verbose;
+ $m->print(loc("Checking...")) if $Verbose;
+
+ # perform some more advanced check
+ if ($Condition) {
+ my $ConditionObj = $Condition->new(
+ TicketObj => $ticket,
+ Argument => $ConditionArg
+ );
+
+ # if the condition doesn't apply, get out of here
+ next unless ( $ConditionObj->IsApplicable );
+ $m->print(loc("Condition matches...")) if $Verbose;
+ }
+
+ if ($Action) {
+ #prepare our action
+ my $ActionObj = $Action->new(
+ TicketObj => $ticket,
+ TemplateObj => $TemplateObj,
+ Argument => $ActionArg
+ );
+
+ #if our preparation, move onto the next ticket
+ next unless ( $ActionObj->Prepare );
+ $m->print(loc("Action prepared...")) if $Verbose;
+
+ #commit our action.
+ next unless ( $ActionObj->Commit );
+ $m->print(loc("Action committed.")) if $Verbose;
+ }
+ }
+ };
+ $m->print('</UL>', loc("Finished."));
+}
+</%INIT>
+<%ARGS>
+$Search => undef
+$SearchArg => undef
+$Condition => undef
+$ConditionArg => undef
+$Action => undef
+$ActionArg => undef
+$TemplateId => undef
+$TemplateObj => undef
+$Verbose => 1
+$NoUI => 0
+</%ARGS>
diff --git a/rt/html/Elements/CollectionAsTable/Row b/rt/html/Elements/CollectionAsTable/Row
index 64ecef41c..0de362ea8 100644
--- a/rt/html/Elements/CollectionAsTable/Row
+++ b/rt/html/Elements/CollectionAsTable/Row
@@ -2,7 +2,7 @@
%#
%# COPYRIGHT:
%#
-%# This software is Copyright (c) 1996-2007 Best Practical Solutions, LLC
+%# This software is Copyright (c) 1996-2005 Best Practical Solutions, LLC
%# <jesse@bestpractical.com>
%#
%# (Except where explicitly superseded by other copyright notices)
@@ -22,9 +22,7 @@
%#
%# 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/copyleft/gpl.html.
+%# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
%#
%#
%# CONTRIBUTION SUBMISSION POLICY:
@@ -55,17 +53,17 @@ $Warning => undef
</%ARGS>
<%PERL>
-$m->out('<tr class="' . ( $Warning ? 'warnline' : $i % 2 ? 'oddline' : 'evenline' ) . '" >' );
+$m->out('<TR class="' . ( $Warning ? 'warnline' : $i % 2 ? 'oddline' : 'evenline' ) . '" >' );
my $item;
foreach my $column (@Format) {
- if ( defined $column->{title} && $column->{title} eq 'NEWLINE' ) {
+ if ( $column->{title} eq 'NEWLINE' ) {
while ( $item < $maxitems ) {
$m->out(qq{<td class="collection-as-table">&nbsp;</td>\n});
$item++;
}
$item = 0;
- $m->out('</tr>');
- $m->out('<tr class="'
+ $m->out('</TR>');
+ $m->out('<TR class="'
. ( $Warning ? 'warnline' : $i % 2 ? 'oddline' : 'evenline' )
. '" >' );
next;
@@ -101,7 +99,7 @@ foreach my $column (@Format) {
# Simple value; just escape it.
@out = $m->interp->apply_escapes( $value => 'h' );
}
- s/\n/<br \/>/gs for @out;
+ s/\n/<br>/gs for @out;
$m->out( @out );
}
else {
@@ -110,5 +108,5 @@ foreach my $column (@Format) {
}
$m->out('</td>');
}
-$m->out('</tr>');
+$m->out('</TR>');
</%PERL>
diff --git a/rt/html/Elements/Footer b/rt/html/Elements/Footer
index 16f13f9fc..78a116f38 100644
--- a/rt/html/Elements/Footer
+++ b/rt/html/Elements/Footer
@@ -2,7 +2,7 @@
%#
%# COPYRIGHT:
%#
-%# This software is Copyright (c) 1996-2007 Best Practical Solutions, LLC
+%# This software is Copyright (c) 1996-2005 Best Practical Solutions, LLC
%# <jesse@bestpractical.com>
%#
%# (Except where explicitly superseded by other copyright notices)
@@ -22,9 +22,7 @@
%#
%# 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/copyleft/gpl.html.
+%# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
%#
%#
%# CONTRIBUTION SUBMISSION POLICY:
@@ -45,27 +43,22 @@
%# those contributions and any derivatives thereof.
%#
%# END BPS TAGGED BLOCK }}}
-%# End of div#body from /Elements/PageLayout
-</div>
+% if ($Menu) {
+</td>
+</tr>
+<tr>
+<td>
+% }
<& /Elements/Callback, %ARGS &>
-<div id="footer">
- <p id="time">
- <span><&|/l&>Time to display</&>: <%Time::HiRes::tv_interval( $m->{'rt_base_time'} )%></span>
- </p>
-
- <p id="bpscredits">
- <span>
-<&|/l, '&#187;&#124;&#171;', $RT::VERSION, '2006', '<a href="http://www.bestpractical.com?rt='.$RT::VERSION.'">Best Practical Solutions, LLC</a>', &>[_1] RT [_2] Copyright 1996-[_3] [_4].</&>
-</span>
-</p>
+<!--
+<div class="bpscredits">
+<&|/l, '&#187;&#124;&#171;', $RT::VERSION, '2005', '<a href="http://www.bestpractical.com?rt='.$RT::VERSION.'">Best Practical Solutions, LLC</a>', &>[_1] RT [_2] Copyright 1996-[_3] [_4].</&><br>
% if (!$Menu) {
- <p id="legal">
-<&|/l&>Distributed under version 2 <a href="http://www.gnu.org/copyleft/gpl.html"> of the GNU GPL.</a></&><br />
-<&|/l, '<a href="mailto:sales@bestpractical.com">sales@bestpractical.com</a>' &>To inquire about support, training, custom development or licensing, please contact [_1].</&><br />
- </p>
+<&|/l&>Distributed under version 2 <a href="http://www.gnu.org/copyleft/gpl.html"> of the GNU GPL.</a></&><br>
+<&|/l, '<a href="mailto:sales@bestpractical.com">sales@bestpractical.com</a>' &>To inquire about support, training, custom development or licensing, please contact [_1].</&><br>
% }
-
</div>
+-->
% if ($Debug >= 2 ) {
% require Data::Dumper;
% my $d = Data::Dumper->new([\%ARGS], [qw(%ARGS)]);
@@ -73,9 +66,17 @@
<%$d->Dump() %>
</pre>
% }
-
- </body>
-</html>
+<div class="page-stats"><&|/l&>Time to display</&>: <%Time::HiRes::tv_interval( $m->{'rt_base_time'} )%></div>
+% if ($Menu) {
+</TD>
+</TR>
+</TABLE>
+</TD>
+</TR>
+</TABLE>
+% }
+</BODY>
+</HTML>
% $m->abort();
<%ARGS>
diff --git a/rt/html/Elements/FreesideInvoiceSearch b/rt/html/Elements/FreesideInvoiceSearch
new file mode 100644
index 000000000..3842b2ff9
--- /dev/null
+++ b/rt/html/Elements/FreesideInvoiceSearch
@@ -0,0 +1,20 @@
+% if ( $FS::CurrentUser::CurrentUser->access_right('View invoices') ) {
+
+ <form action="<% $RT::URI::freeside::URL %>/search/cust_bill.html" STYLE="margin:0">
+ <SCRIPT TYPE="text/javascript">
+ function clearhint_search_invoice (what) {
+ if ( what.value == '(inv #)' )
+ what.value = '';
+ }
+ </SCRIPT>
+ <input name="invnum" accesskey="0" VALUE="(inv #)" SIZE="4" onFocus="clearhint_search_invoice(this);" onClick="clearhint_search_invoice(this);" STYLE="text-align:right; margin-bottom:1px; font-family: Arial, Verdana, Helvetica, sans-serif;">
+
+% if ( $FS::CurrentUser::CurrentUser->access_right('List invoices') ) {
+ <A HREF="<% $RT::URI::freeside::URL %>search/report_cust_bill.html" STYLE="color: #ffffff; font-size: 70%; font-weight:normal">Advanced</A>
+% }
+ <BR>
+
+ <input type="submit" value="<&|/l&>Search invoices</&>" CLASS="fsblackbutton" onMouseOver="this.className='fsblackbuttonselected'; return true;" onMouseOut="this.className='fsblackbutton'; return true;" STYLE="font-size:70%">
+ </form>
+
+% }
diff --git a/rt/html/Elements/FreesideNewCust b/rt/html/Elements/FreesideNewCust
new file mode 100644
index 000000000..c752437da
--- /dev/null
+++ b/rt/html/Elements/FreesideNewCust
@@ -0,0 +1,3 @@
+<form action="<% $RT::URI::freeside::URL %>/edit/cust_main.cgi" STYLE="margin:0">
+<INPUT TYPE="submit" VALUE="<&|/l&>New customer</&>" CLASS="fsblackbutton" onMouseOver="this.className='fsblackbuttonselected'; return true;" onMouseOut="this.className='fsblackbutton'; return true;">&nbsp;
+</FORM>
diff --git a/rt/html/Elements/FreesideSearch b/rt/html/Elements/FreesideSearch
new file mode 100644
index 000000000..2fed8fc73
--- /dev/null
+++ b/rt/html/Elements/FreesideSearch
@@ -0,0 +1,11 @@
+<form action="<% $RT::URI::freeside::URL %>/search/cust_main.cgi" STYLE="margin:0">
+ <SCRIPT TYPE="text/javascript">
+ function clearhint_search_cust (what) {
+ if ( what.value == '(cust #, name, company or phone)' )
+ what.value = '';
+ }
+ </SCRIPT>
+<input name="search_cust" accesskey="0" VALUE="(cust #, name, company or phone)" SIZE="28" onFocus="clearhint_search_cust(this);" onClick="clearhint_search_cust(this);" STYLE="text-align:right; font-family: Arial, Verdana, Helvetica, sans-serif;"><BR>
+<A NOTYET="<% $RT::URI::freeside::URL %>/search/cust_main.html" STYLE="color: #000000; font-size: 70%; font-weight:normal">Advanced</A>
+<input type="submit" value="<&|/l&>Search customers</&>" CLASS="fsblackbutton" onMouseOver="this.className='fsblackbuttonselected'; return true;" onMouseOut="this.className='fsblackbutton'; return true;" STYLE="font-size:70%">
+</form>
diff --git a/rt/html/Elements/FreesideSvcSearch b/rt/html/Elements/FreesideSvcSearch
new file mode 100644
index 000000000..4a5942421
--- /dev/null
+++ b/rt/html/Elements/FreesideSvcSearch
@@ -0,0 +1,11 @@
+<form action="<% $RT::URI::freeside::URL %>/search/cust_svc.html" STYLE="margin:0">
+ <SCRIPT TYPE="text/javascript">
+ function clearhint_search_svc (what) {
+ if ( what.value == '(user, user@domain or domain)' )
+ what.value = '';
+ }
+ </SCRIPT>
+<input name="search_svc" accesskey="0" VALUE="(user, user@domain or domain)" SIZE="26" onFocus="clearhint_search_svc(this);" onClick="clearhint_search_svc(this);" STYLE="text-align:right; font-family: Arial, Verdana, Helvetica, sans-serif;"><BR>
+ <A NOTYET="<% $RT::URI::freeside::URL %>search/svc_Smarter.html" STYLE="color: #000000; font-size: 70%; font-weight:normal">Advanced</A>
+<input type="submit" value="<&|/l&>Search services</&>" CLASS="fsblackbutton" onMouseOver="this.className='fsblackbuttonselected'; return true;" onMouseOut="this.className='fsblackbutton'; return true;" STYLE="font-size:70%">
+</form>
diff --git a/rt/html/Elements/Header b/rt/html/Elements/Header
index ed7c133b6..b5512aae9 100644
--- a/rt/html/Elements/Header
+++ b/rt/html/Elements/Header
@@ -2,7 +2,7 @@
%#
%# COPYRIGHT:
%#
-%# This software is Copyright (c) 1996-2007 Best Practical Solutions, LLC
+%# This software is Copyright (c) 1996-2005 Best Practical Solutions, LLC
%# <jesse@bestpractical.com>
%#
%# (Except where explicitly superseded by other copyright notices)
@@ -22,9 +22,7 @@
%#
%# 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/copyleft/gpl.html.
+%# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
%#
%#
%# CONTRIBUTION SUBMISSION POLICY:
@@ -45,89 +43,103 @@
%# those contributions and any derivatives thereof.
%#
%# END BPS TAGGED BLOCK }}}
-<!DOCTYPE html
- PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
- "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-
-<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"><head>
-
-<title><%$Title%></title>
-
+%#<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<HTML>
+<HEAD>
+<TITLE><%$Title%></TITLE>
% if ($Refresh && $Refresh > 0) {
- <meta http-equiv="refresh" content="<%$Refresh%>" />
+<META HTTP-EQUIV="REFRESH" CONTENT="<%$Refresh%>">
% }
<link rel="shortcut icon" href="<%$RT::WebImagesURL%>/favicon.png" type="image/png" />
-<link rel="stylesheet" href="<%$RT::WebPath%>/NoAuth/css/<% $RT::WebDefaultStylesheet %>/main.css" type="text/css" media="all" />
-<link rel="stylesheet" href="<%$RT::WebPath%>/NoAuth/css/print.css" type="text/css" media="print" />
+<link media="all" rel="stylesheet" href="<%$RT::WebPath%>/NoAuth/webrt.css" type="text/css" />
+<link media="print" rel="stylesheet" href="<%$RT::WebPath%>/NoAuth/printrt.css" type="text/css" />
-% if ( $RSSAutoDiscovery ) {
- <link rel="alternate" href="<%$RSSAutoDiscovery%>" type="application/rss+xml" title="RSS RT Search" />
+<script>
+function hideshow(num) {
+ idstring = "element-" + num;
+ chunk = document.getElementById(idstring);
+ if ( chunk.style.display == "none") {
+ chunk.style.display = chunk.style.tag;
+ } else {
+ chunk.style.tag = chunk.style.display;
+ chunk.style.display = "none";
+ }
+}
+</script>
+<& /Elements/Callback, _CallbackName => 'Head', %ARGS &>
+</HEAD>
+<BODY BACKGROUND="<% $RT::URI::freeside::URL %>/images/background-cheat.png" STYLE="margin-top:0; margin-bottom:0; margin-left:0; margin-right:0"
+% if ($Focus) {
+ONLOAD="
+ var tmp = (document.getElementsByName('<% $Focus %>'));
+ if (tmp.length > 0) tmp[tmp.length-1].focus();
+"
% }
-
-<script type="text/javascript" src="<%$RT::WebPath%>/NoAuth/js/util.js"></script>
-<script type="text/javascript" src="<%$RT::WebPath%>/NoAuth/js/ahah.js"></script>
-<script type="text/javascript" src="<%$RT::WebPath%>/NoAuth/js/titlebox-state.js"></script>
-<script type="text/javascript"><!--
- onLoadHook("loadTitleBoxStates()");
-% if ( $Focus ) {
- onLoadHook("focusElementById('<% $Focus %>')");
+>
+<table width="100%" border="0" cellspacing="0" cellpadding="0" bgcolor="#FFFFFF" STYLE="padding-left:0; padding-right:4">
+ <tr>
+ <td colspan=2 rowspan=2><img border=0 alt="freeside" src="<%$RT::WebImagesURL%>/small-logo.png" width="92" height="62"></td>
+ <td align="left" rowspan=2><font size=6><% &RT::URI::freeside::FreesideGetConfig('company_name') || 'ExampleCo' %></font></td>
+ <td align="right" valign="top">
+% if ($session{'CurrentUser'} && $session{'CurrentUser'}->Id && $LoggedIn) {
+<SPAN STYLE="display: none"><A HREF="#skipnav"><&|/l&>Skip Menu</&></A> |</SPAN>
+<&|/l, "<b>".$session{'CurrentUser'}->Name."</b>" &>Logged in as [_1]</&>
+<BR>
+%if ($session{'CurrentUser'}->HasRight( Right => 'ModifySelf', Object => $RT::System )) {
+<A HREF="<%$RT::WebPath%><% $Prefs %>" ><&|/l&>Preferences</&></A>
% }
-% if ( $onload ) {
- onLoadHook("<% $onload |n %>");
+<& /Elements/Callback, %ARGS &>
+% unless ($RT::WebExternalAuth and !$RT::WebFallbackToInternalAuth) {
+| <A HREF="<%$RT::WebPath%>/NoAuth/Logout.html<%$URL ? "?URL=".$URL : ''%>"><&|/l&>Logout</&></a>
% }
---></script>
-
-<& /Elements/Callback, _CallbackName => 'Head', %ARGS &>
+% } else {
+<&|/l&>Not logged in.</&>
+% }
+ </td>
-</head>
- <body<% $id && qq[ id="comp-$id"] |n %>>
+ </tr>
+ <tr>
-% if ($ShowBar) {
-<& /Elements/Logo &>
+ <td align=right valign=bottom>
+ <table>
+ <tr>
+ <td align=right>
+ <FONT SIZE="-3">
+ <A HREF="http://www.sisd.com/freeside">Freeside</A>&nbsp;v<% &RT::URI::freeside::FreesideVersion() %><BR>
+ <A HREF="<% FS::Conf->new->config('support-key') ? "http://www.sisd.com/mediawiki/index.php/Supported:Documentation" : "http://www.sisd.com/mediawiki/index.php/Freeside:1.7:Documentation" %>">Documentation</A><BR>
+ </FONT>
+ </td>
+ <td bgcolor=#000000></td>
+ <td align=left>
+ <FONT SIZE="-3">
+ <A HREF="http://www.bestpractical.com/rt">RT</A>&nbsp;v<% $RT::VERSION %><BR>
+ <A HREF="http://wiki.bestpractical.com/">Documentation</A><BR>
+ </FONT>
+ </td>
-<div id="quickbar">
- <div id="quick-personal">
- <span class="hide"><a href="#skipnav"><&|/l&>Skip Menu</&></a> | </span>
-% if ($session{'CurrentUser'}->Name) {
- <&|/l, "<span>".$session{'CurrentUser'}->Name."</span>" &>Logged in as [_1]</&>
-% if ($session{'CurrentUser'}->HasRight( Right => 'ModifySelf', Object => $RT::System )) {
- | <a href="<%$RT::WebPath%><%$Prefs%>"><&|/l&>Preferences</&></a>
-% }
-% } else {
- <&|/l&>Not logged in.</&>
-% }
- <& /Elements/Callback, %ARGS &>
-% unless (!$session{'CurrentUser'}->Name
-% or ($RT::WebExternalAuth and !$RT::WebFallbackToInternalAuth)) {
- | <a href="<%$RT::WebPath%>/NoAuth/Logout.html<%$URL ? "?URL=".$URL : ''%>"><&|/l&>Logout</&></a>
-% }
- </div>
-% }
+ </tr>
+ </table>
+ </td>
+ </tr>
+</table>
<%INIT>
+
$r->headers_out->{'Pragma'} = 'no-cache';
$r->headers_out->{'Cache-control'} = 'no-cache';
-
-my $id = $m->request_comp->path;
-$id =~ s|^/||g;
-$id =~ s|/|-|g;
-$id =~ s|\.html$||g;
-$id =~ s|index$||g
- if $id ne 'index';
-$id =~ s|-$||g;
+require RT::URI::freeside;
</%INIT>
<%ARGS>
$Prefs => '/User/Prefs.html'
-#$Focus => 'focus'
-$Focus => ''
+$Focus => 'focus'
$Title => 'RT'
$Code => undef
$Refresh => 0
$Why => undef
+$BgColor => '#ffffff'
$ShowBar => 1
+$LoggedIn => 1
$URL => undef
-$RSSAutoDiscovery => undef
-$onload => undef
</%ARGS>
diff --git a/rt/html/Elements/Menu b/rt/html/Elements/Menu
index b5b2bdad5..398e3ab07 100644
--- a/rt/html/Elements/Menu
+++ b/rt/html/Elements/Menu
@@ -2,7 +2,7 @@
%#
%# COPYRIGHT:
%#
-%# This software is Copyright (c) 1996-2007 Best Practical Solutions, LLC
+%# This software is Copyright (c) 1996-2005 Best Practical Solutions, LLC
%# <jesse@bestpractical.com>
%#
%# (Except where explicitly superseded by other copyright notices)
@@ -22,9 +22,7 @@
%#
%# 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/copyleft/gpl.html.
+%# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
%#
%#
%# CONTRIBUTION SUBMISSION POLICY:
@@ -45,90 +43,66 @@
%# those contributions and any derivatives thereof.
%#
%# END BPS TAGGED BLOCK }}}
-<ul<% !$level ? ' id="system-menu"' : ''|n %><% $menu_class ? qq[ class="$menu_class"] : ''|n %>>
-<div<% $menu_class ? qq[ class="$menu_class"] : ''|n %>><div class="wrapper">
-% my $sep = 0;
-% my $postsep = 0;
-% my $accesskey = 1;
-%
-% $count = 0;
-% $class = {};
-%
+%# font size depends on level
+% if ($level ge 3) {
+% $size = $basesize-(6);
+% } elsif ($level gt 0) {
+% $size = $basesize-($level * 2);
+% $padding = 2;
+% }
+% else {
+% $size = $basesize;
+% $padding = 5;
+% }
+<ul class="topnav" >
+% my $sep=0;
+% my $accesskey="1";
% foreach $tab (sort keys %{$toptabs}) {
-% $count++;
-%
-% my $current = $current_toptab || "";
-% my $path = $toptabs->{$tab}->{'path'} || "";
-%
-% $path =~ s#/index.html$##gi;
-% $current =~ s#/index.html$##gi;
-%
-% $sep = $toptabs->{$tab}->{'separator'} ? 1 : 0;
-%
-% my @aclass;
-% push @aclass, 'selected'
-% if $path eq $current;
-%
-% push @aclass, 'odd'
-% if $level % 2;
-%
-% $class->{a} = join ' ', @aclass;
-%
-% my @li;
-% push @li, 'first'
-% if $count == 1;
-%
-% push @li, 'pre-separator'
-% if $sep;
-%
-% push @li, 'post-separator'
-% if $postsep;
-%
-% $class->{li} = join ' ', @li;
-%
-% my $url = ($toptabs->{$tab}->{'path'}||'') =~ /^https?:/i
-% ? $toptabs->{$tab}->{'path'} || ''
-% : $RT::WebPath . "/" . $toptabs->{$tab}->{'path'};
-%
- <li<% $class->{li} ? qq[ class="$class->{li}"] : ''|n %>>
- <% $count > 1 && !$postsep && qq[<span class="bullet">&#183; </span>]|n%>
- <a href="<% $url %>"
- <% $class->{a} && qq[ class="$class->{a}"] |n%>
- <% !$level && " accesskey='".$accesskey++."'" |n%>>
- <% $toptabs->{$tab}->{'title'} || ''%></a>
+% my $current = $current_toptab || "";
+% my $path = $toptabs->{$tab}->{'path'} || "";
+% $path =~ s#/index.html$##gi;
+% $current =~ s#/index.html$##gi;
+% if ( $path eq $current) {
+% $class="currenttopnav"
+% } else {
+% $class="topnav"
+% }
+% my $style="";
+% if ($sep) {
+% $style="minor";
+% } elsif ($level == 0 ) {
+% $style="major";
+% }
+% if ($toptabs->{$tab}->{'separator'}) {
+% $sep=1;
+% } else {
+% $sep=0;
+% }
+% my $url = $toptabs->{$tab}->{'path'} =~ /^https?:/i ? $toptabs->{$tab}->{'path'} : $RT::WebPath . "/" . $toptabs->{$tab}->{'path'};
+<li class="<%$class%>-<%$level%>-<%$style%>"><A HREF="<% $url %>" class="<%$class%>-<%$level%>"
+<%($class eq 'currenttopnav') ? "name='focus'" : ""|n %>
+<% !$level && "accesskey='".$accesskey++."'" |n%>><% $toptabs->{$tab}->{'title'}%></A>
%# Second-level items
-% if ($toptabs->{$tab}->{'subtabs'}
-% and keys %{$toptabs->{$tab}->{'subtabs'}})
-% {
- <& /Elements/Menu, level => $level+1,
- current_toptab => $toptabs->{$tab}->{'current_subtab'},
- toptabs => $toptabs->{$tab}->{'subtabs'},
- last_level => $toptabs->{$tab}->{last_system_menu_level} &>
-% }
- </li>
-% if ($sep) {
- <li class="separator">&#183;&#183;&#183;</li>
-% }
-%
-% $postsep = $sep;
+%# if ($current_toptab eq $toptabs->{$tab}->{'path'}) {
+%# commented out by jesse on 4 jan 2003 so that tickets/search and ticket/# can
+%# both have menu items
+% if ($toptabs->{$tab}->{'subtabs'}) {
+ <& /Elements/Menu, level => $level+1,
+ current_toptab => $toptabs->{$tab}->{'current_subtab'},
+ toptabs => $toptabs->{$tab}->{'subtabs'} &></li>
+% }
+%# }
% }
-</div></div>
</ul>
<%INIT>
-my ($tab, $class, $count);
+my ($tab, $subtab, $class, $size, $padding);
+my $basesize=16;
-my @ul;
-push @ul, 'last-menu-level'
- if $last_level;
-push @ul, 'odd'
- if $level % 2;
-my $menu_class = join ' ', @ul;
</%INIT>
<%ARGS>
$current_toptab => ""
$toptabs => undef
$level => 0
-$last_level => 0
</%ARGS>
diff --git a/rt/html/Elements/PageLayout b/rt/html/Elements/PageLayout
index 493f2275f..f13ee0dda 100644
--- a/rt/html/Elements/PageLayout
+++ b/rt/html/Elements/PageLayout
@@ -2,7 +2,7 @@
%#
%# COPYRIGHT:
%#
-%# This software is Copyright (c) 1996-2007 Best Practical Solutions, LLC
+%# This software is Copyright (c) 1996-2005 Best Practical Solutions, LLC
%# <jesse@bestpractical.com>
%#
%# (Except where explicitly superseded by other copyright notices)
@@ -22,9 +22,7 @@
%#
%# 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/copyleft/gpl.html.
+%# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
%#
%#
%# CONTRIBUTION SUBMISSION POLICY:
@@ -45,124 +43,72 @@
%# those contributions and any derivatives thereof.
%#
%# END BPS TAGGED BLOCK }}}
- <div id="topactions">
-% foreach my $action (reverse sort keys %{$topactions}) {
- <span class="topaction">
-% $m->out($topactions->{"$action"}->{'html'});
- </span>
+<table class="black" border=0 cellspacing=0 cellpadding=0 width="100%">
+<tr>
+ <TD colspan=5 WIDTH="100%" STYLE="padding:0"><IMG BORDER=0 ALT="" SRC="<% $RT::URI::freeside::URL %>/images/black-gradient.png" HEIGHT="13" WIDTH="100%"></TD>
+</tr>
+<tr>
+%# <th class="black" align="left" width=15%><span class="rtname"><%$AppName%></span>
+%# </th>
+ <span class="topactions">
+% my $notfirst = 0; foreach my $action (sort keys %{$topactions}) {
+ <td class="blackright" ALIGN="right" VALIGN="center">
+ <%$topactions->{"$action"}->{'html'} |n %>
+ </td>
% }
- </div>
-
-%# End of div#quickbar from /Elements/Header
-</div>
-
-<div id="nav">
-<& /Elements/Menu, toptabs => $toptabs, current_toptab => $current_toptab &>
-</div>
-
-<div id="header">
- <h1><%$title%></h1>
-
-% my $sep = 0;
-% my $postsep = 0;
-% my $count = 0;
-% my $class = { };
-%
- <ul id="page-menu"<% (($actions && %$actions) || ($subactions && %$subactions)) && q[ class="actions-present"] | n %>>
- <div><div><div>
-% if ($page_tabs) {
-% foreach my $tab (sort keys %{$page_tabs}) {
-% next if $tab =~ /^(?:current_toptab|this)$/;
-% $count++;
-%
-% my $current = $page_tabs->{current_toptab} || "";
-% my $path = $page_tabs->{$tab}->{'path'} || "";
-%
-% $path =~ s#/index.html$##gi;
-% $current =~ s#/index.html$##gi;
-%
-% $sep = $toptabs->{$tab}->{'separator'} ? 1 : 0;
-%
-% $class->{a} = $path eq $current ? ' class="selected"' : undef;
-%
-% my @li;
-% push @li, 'first'
-% if $count == 1;
-%
-% push @li, 'pre-separator'
-% if $sep;
-%
-% push @li, 'post-separator'
-% if $postsep;
-%
-% $class->{li} = join ' ', @li;
-%
-%
- <li<% $class->{li} ? qq[ class="$class->{li}"] : ''|n %>><% $count > 1 && !$postsep && "&#183; "|n%><a href="<%$RT::WebPath%>/<%$page_tabs->{$tab}->{'path'}%>"<%$class->{a}|n%><% $class->{a} ? ' name="focus"' : ''|n %>><% $page_tabs->{$tab}->{'title'} %></a></li>
-%
-% if ($sep) {
- <li class="separator">&#183;&#183;&#183;</li>
-% }
-% $postsep = $sep;
-% }
+ </span>
+</tr>
+</table>
+<table border=0 cellspacing=0 cellpadding=0 width="100%" height="100%">
+<TR>
+ <TD BGCOLOR="#000000" STYLE="padding:0" WIDTH="154"></TD>
+ <TD STYLE="padding:0" WIDTH="13"><IMG BORDER=0 ALT="" SRC="<% $RT::URI::freeside::URL %>/images/black-gray-corner.png"></TD>
+ <TD STYLE="padding:0"><IMG BORDER=0 ALT="" SRC="<% $RT::URI::freeside::URL %>/images/black-gray-top.png" HEIGHT="13" WIDTH="100%"></TD>
+</TR>
+%# Vertical menu
+<TR height="100%">
+<TD valign="top" width="140" class="black">
+ <& /Elements/Menu, toptabs => $toptabs, current_toptab => $current_toptab &>
+</TD>
+<TD STYLE="padding:0" HEIGHT="100%" WIDTH=13 VALIGN="top"><IMG WIDTH="13" HEIGHT="100%" BORDER=0 ALT="" SRC="<% $RT::URI::freeside::URL %>/images/black-gray-side.png"></TD>
+<td valign="top">
+<table width="100%" height="100%" border="0" cellpadding="0" cellspacing="0">
+<tr>
+ <td class="<% $actions ? 'darkmediumgray' : 'bggray' %>" valign="top">
+ <span class="title"><%$title%></span>
+</td>
+</tr>
+<tr>
+<td class="<% $actions ? 'darkmediumgrayright' : 'bggrayright' %>" valign="top">
+ <span class="nav">
+% if ($actions) {
+% my @actions;
+% foreach my $action (sort keys %{$actions}) {
+% if ($actions->{"$action"}->{'html'}) {
+% push @actions, $actions->{"$action"}->{'html'};
% } else {
-&nbsp;
-% }
- </div></div></div>
- </ul>
-
-% if (($actions && %$actions) || ($subactions && %$subactions)) {
- <ul id="actions-menu">
- <div><div><div>
-% $sep = 0;
-% $postsep = 0;
-% $count = 0;
-% $class = { };
-%
-% for my $type ($actions, $subactions) {
-%
-% if ($type && %$type) {
-% foreach my $action (sort keys %{$type}) {
-% $count++;
-%
-% $sep = $type->{$action}->{'separator'} ? 1 : 0;
-%
-% my @li;
-% push @li, 'first'
-% if $count == 1;
-%
-% push @li, 'pre-separator'
-% if $sep;
-%
-% push @li, 'post-separator'
-% if $postsep;
-%
-% $class->{li} = join ' ', @li;
-%
- <li<% $class->{li} ? qq[ class="$class->{li}"] : ''|n %>><% $count > 1 && !$postsep && qq[<span class="bullet">&#183; </span>]|n%>
-% if ($type->{"$action"}->{'html'}) {
- <% $type->{"$action"}->{'html'} | n %>
-% } else {
- <a href="<%$RT::WebPath%>/<%$type->{$action}->{'path'}%>"<% $type->{$action}->{class} && ' class="'.$type->{$action}->{class}.'"' |n %><% $type->{$action}->{id} && ' id="'.$type->{$action}->{id}.'"' |n %>><%$type->{$action}->{'title'}%></a>
-% }
- </li>
-% if ($sep) {
- <li class="separator">&#183;&#183;&#183;</li>
-% }
-% $postsep = $sep;
-% }
+% push @actions, qq|<a class="nav" href="|.$RT::WebPath."/".$actions->{$action}->{'path'}.qq|">|.$actions->{$action}->{'title'}."</a>";
% }
+% }
+%#<% join(" | ", @actions) | n %>
+<% '['. join("] [", @actions). ']&nbsp;' | n %>
+% if ($subactions) {
+% my @actions;
+% foreach my $action (sort keys %{$subactions}) {
+% push @actions, $subactions->{"$action"}->{'html'};
+% }
+<% join(" | ", @actions) | n %>
% }
- </div></div></div>
- </ul>
% }
-</div>
-
-<div id="body">
+ </span>
+ </td>
+</tr>
+<TR valign="top">
+<TD valign="top" width="100%" height="100%" class="mainbody" >
<& /Elements/Callback, _CallbackName => 'BeforeBody', %ARGS &>
%$m->flush_buffer(); # we've got the page laid out, let's flush the buffer;
-
<%INIT>
+
foreach my $tab (sort keys %{$toptabs}) {
if ($current_toptab && $toptabs->{$tab}->{'path'} eq $current_toptab) {
$toptabs->{$tab}->{"subtabs"} = $tabs;
@@ -174,53 +120,7 @@ if (! defined($AppName)) {
$AppName = loc("RT for [_1]", $RT::rtname);
}
-my ($menu_depth, $almost_last, $page_tabs);
-
-if ($RT::WebDefaultStylesheet ne '3.4-compat') {
- ($menu_depth, $almost_last) = @{$m->comp('.menu_recurse', data => $toptabs)};
-
- if (defined $almost_last->{subtabs} and %{$almost_last->{subtabs}}) {
- $page_tabs = {
- current_toptab => $almost_last->{current_subtab},
- %{$almost_last->{subtabs}},
- };
-
- delete $almost_last->{subtabs};
- delete $almost_last->{current_subtab};
- }
-}
</%INIT>
-
-%# There's probably a better way to do this that involves three times as
-%# much work and redoing the whole menu/tab system... which would seem a
-%# bit out of scope.
-%#
-%# This function recurses through the menu and returns the second to
-%# last menu, that is, the menu holding the last reference to
-%# and submenu. It also returns the number of menu levels minus
-%# the last submenu.
-<%def .menu_recurse>
- <%args>
- $data => { }
- $pdata => { }
- $ppdata => { }
- $level => 0
- </%args>
- <%init>
- for my $key (keys %$data) {
- return $m->comp('.menu_recurse', data => $data->{$key}->{subtabs},
- pdata => $data->{$key},
- ppdata => $pdata,
- level => $level+1)
- if ref($data->{$key}) eq 'HASH'
- and defined $data->{$key}->{subtabs}
- and %{$data->{$key}->{subtabs}};
- }
- $ppdata->{last_system_menu_level}++;
- return [$level, $pdata];
- </%init>
-</%def>
-
<%ARGS>
$current_toptab => undef
$current_tab => undef
@@ -230,5 +130,5 @@ $tabs => undef
$actions => undef
$subactions => undef
$title => $m->callers(-1)->path
-$AppName => undef
+$AppName => ''
</%ARGS>
diff --git a/rt/html/Elements/QuickCreate b/rt/html/Elements/QuickCreate
index bad7503b7..0b97121a4 100644
--- a/rt/html/Elements/QuickCreate
+++ b/rt/html/Elements/QuickCreate
@@ -2,7 +2,7 @@
%#
%# COPYRIGHT:
%#
-%# This software is Copyright (c) 1996-2007 Best Practical Solutions, LLC
+%# This software is Copyright (c) 1996-2005 Best Practical Solutions, LLC
%# <jesse@bestpractical.com>
%#
%# (Except where explicitly superseded by other copyright notices)
@@ -22,9 +22,7 @@
%#
%# 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/copyleft/gpl.html.
+%# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
%#
%#
%# CONTRIBUTION SUBMISSION POLICY:
@@ -45,27 +43,28 @@
%# those contributions and any derivatives thereof.
%#
%# END BPS TAGGED BLOCK }}}
-<div class="quick-create">
-<&| /Widgets/TitleBox, title => loc('Quick ticket creation') &>
-<form method="post" action="<%$RT::WebPath%>/index.html">
-<input type="hidden" class="hidden" name="QuickCreate" value="1" />
+<& /Elements/TitleBoxStart, title => loc('Quick ticket creation') &>
+<form method="post" action="<%$RT::WebPath%>/<% $RT::QuickCreateLong ? 'Ticket/Create.html' : 'index.html' %>">
+<input type="hidden" name="QuickCreate" value="1">
<table>
-<tr><td>
-<&|/l&>Subject</&>:<br /><input size="15" name="Subject" />
-</td><td>
-<&|/l&>Queue</&>:<br /><& /Elements/SelectNewTicketQueue, Name => 'Queue', ShowNullOption => 0 &>
-</td><td>
-<&|/l&>Owner</&>:<br />
+<tr>
+<td>
+<font size="-2"><&|/l&>Subject</&>:<br><input size="30" name="Subject"></font>
+</td>
+<td>
+<font size="-2"><&|/l&>Queue</&>:<br><& /Elements/SelectQueue, Name => 'Queue', ShowNullOption => 0 &></font>
+</td>
+<td>
+<font size="-2"><&|/l&>Owner</&>:<br>
<select type="select" name="Owner">
-<option value="<%$session{'CurrentUser'}->id%>" selected><%$session{'CurrentUser'}->Name %></option>
+<option value="<%$session{'CurrentUser'}->id%>" SELECTED><%$session{'CurrentUser'}->Name %></option>
<option value="<%$RT::Nobody->id%>"><%loc('Nobody')%></option>
</select>
+</font>
</td>
</tr>
-%#<tr><td colspan="3"><textarea cols="50" rows="3"></textarea></td></tr>
+%#<tr><td colspan="3"><font size="-2"><textarea cols="50" rows="3"></textarea></font></td></tr>
</table>
-<div align="right"><input type="submit" class="button" value="<%loc('Create')%>" /></div>
+<div align="right"><input type="submit" value="<%loc('Create')%>"></div>
</form>
-</&>
-</div>
-
+<& /Elements/TitleBoxEnd &>
diff --git a/rt/html/Elements/ShadedBox b/rt/html/Elements/ShadedBox
deleted file mode 100644
index 36b9cae7c..000000000
--- a/rt/html/Elements/ShadedBox
+++ /dev/null
@@ -1,33 +0,0 @@
-%# BEGIN LICENSE BLOCK
-%#
-%# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com>
-%#
-%# (Except where explictly superceded by other copyright notices)
-%#
-%# 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.
-%#
-%# Unless otherwise specified, all modifications, corrections or
-%# extensions to this work which alter its source code become the
-%# property of Best Practical Solutions, LLC when submitted for
-%# inclusion in the work.
-%#
-%#
-%# END LICENSE BLOCK
-<table>
- <tr>
- <td class="label"><%$title |n %>:</td>
- <td class="value"><%$content |n %></td>
- </tr>
-</table>
-<%ARGS>
-$title => undef
-$content => "&nbsp;"
-</%ARGS>
diff --git a/rt/html/Elements/ShadedInputRow b/rt/html/Elements/ShadedInputRow
deleted file mode 100644
index e9fb69e5f..000000000
--- a/rt/html/Elements/ShadedInputRow
+++ /dev/null
@@ -1,35 +0,0 @@
-%# BEGIN LICENSE BLOCK
-%#
-%# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com>
-%#
-%# (Except where explictly superceded by other copyright notices)
-%#
-%# 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.
-%#
-%# Unless otherwise specified, all modifications, corrections or
-%# extensions to this work which alter its source code become the
-%# property of Best Practical Solutions, LLC when submitted for
-%# inclusion in the work.
-%#
-%#
-%# END LICENSE BLOCK
-<tr>
- <td class="label"><%$title |n %>:</td>
- <td class="value">
- <input name=<%$name%> value="<%$content|h%>" SIZE=<%$size%>>
- </td>
-</tr>
-<%ARGS>
-$title => undef
-$content => "&nbsp;"
-$name => undef
-$size => undef
-</%ARGS>
diff --git a/rt/html/Elements/ShadedRow b/rt/html/Elements/ShadedRow
deleted file mode 100644
index 8947fcd82..000000000
--- a/rt/html/Elements/ShadedRow
+++ /dev/null
@@ -1,31 +0,0 @@
-%# BEGIN LICENSE BLOCK
-%#
-%# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com>
-%#
-%# (Except where explictly superceded by other copyright notices)
-%#
-%# 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.
-%#
-%# Unless otherwise specified, all modifications, corrections or
-%# extensions to this work which alter its source code become the
-%# property of Best Practical Solutions, LLC when submitted for
-%# inclusion in the work.
-%#
-%#
-%# END LICENSE BLOCK
-<tr>
- <td class="label"><%$title |n %>:</td>
- <td class="value"><%$content |n %></td>
-</tr>
-<%ARGS>
-$title => undef
-$content => "&nbsp;"
-</%ARGS>
diff --git a/rt/html/Elements/SimpleSearch b/rt/html/Elements/SimpleSearch
index 78abce467..e9fc5c6ed 100644
--- a/rt/html/Elements/SimpleSearch
+++ b/rt/html/Elements/SimpleSearch
@@ -2,7 +2,7 @@
%#
%# COPYRIGHT:
%#
-%# This software is Copyright (c) 1996-2007 Best Practical Solutions, LLC
+%# This software is Copyright (c) 1996-2005 Best Practical Solutions, LLC
%# <jesse@bestpractical.com>
%#
%# (Except where explicitly superseded by other copyright notices)
@@ -22,9 +22,7 @@
%#
%# 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/copyleft/gpl.html.
+%# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
%#
%#
%# CONTRIBUTION SUBMISSION POLICY:
@@ -45,7 +43,14 @@
%# those contributions and any derivatives thereof.
%#
%# END BPS TAGGED BLOCK }}}
-<form action="<% $RT::WebPath %>/Search/Simple.html">
- <input size="12" name="q" autocomplete="off" accesskey="0" class="field" />
- <input type="submit" class="button" value="<&|/l&>Search</&>" />
+<form action="<% $RT::WebPath %>/index.html" STYLE="margin:0">
+<SCRIPT TYPE="text/javascript">
+ function clearhint_search_ticket (what) {
+ if ( what.value == '(ticket # or subject string)' )
+ what.value = '';
+ }
+</SCRIPT>
+<input name="q" accesskey="0" VALUE="(ticket # or subject string)" onFocus="clearhint_search_ticket(this);" onClick="clearhint_search_ticket(this);" STYLE="text-align:right; font-family: Arial, Verdana, Helvetica, sans-serif;"><BR>
+<A HREF="<% $RT::WebPath %>/Search/Build.html" STYLE="color: #ffffff; font-size: 70%; font-weight:normal">Advanced</A>
+<input type="submit" value="<&|/l&>Search tickets</&>" CLASS="fsblackbutton" onMouseOver="this.className='fsblackbuttonselected'; return true;" onMouseOut="this.className='fsblackbutton'; return true;" STYLE="font-size:70%;padding-left:2px;padding-right:2px">
</form>
diff --git a/rt/html/Elements/Tabs b/rt/html/Elements/Tabs
index 5afc54a84..bbea3fe9a 100644
--- a/rt/html/Elements/Tabs
+++ b/rt/html/Elements/Tabs
@@ -2,7 +2,7 @@
%#
%# COPYRIGHT:
%#
-%# This software is Copyright (c) 1996-2007 Best Practical Solutions, LLC
+%# This software is Copyright (c) 1996-2005 Best Practical Solutions, LLC
%# <jesse@bestpractical.com>
%#
%# (Except where explicitly superseded by other copyright notices)
@@ -22,9 +22,7 @@
%#
%# 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/copyleft/gpl.html.
+%# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
%#
%#
%# CONTRIBUTION SUBMISSION POLICY:
@@ -59,22 +57,32 @@
<%INIT>
my $action;
my $basetopactions = {
- A => { html => $m->scomp('/Elements/CreateTicket')
+# A => { html => $m->scomp('/Elements/CreateTicket')
+# },
+ A => { html => $m->scomp('/Elements/FreesideNewCust')
},
- B => { html => $m->scomp('/Elements/SimpleSearch')
+ B => { html => $m->scomp('/Elements/FreesideSearch')
+ },
+ C => { html => $m->scomp('/Elements/FreesideInvoiceSearch')
+ },
+ D => { html => $m->scomp('/Elements/FreesideSvcSearch')
+ },
+ E => { html => $m->scomp('/Elements/SimpleSearch')
}
};
-my $basetabs = { A => { title => loc('Homepage'),
- path => '',
+my $basetabs = {
+ ' A'=> { title => 'Billing Main',
+ path => &RT::URI::freeside::FreesideURL(),
},
- Ab => { title => loc('Simple Search'),
- path => 'Search/Simple.html'
+ A => { #title => loc('Homepage'),
+ title => 'Ticketing Main',
+ path => '',
},
- B => { title => loc('Tickets'),
+ B => { title => loc('Search Tickets'),
path => 'Search/Build.html'
},
C => { title => loc('Tools'),
- path => 'Tools/index.html'
+ path => 'Tools/Offline.html'
},
P => { title => loc('Approval'),
path => 'Approvals/'
@@ -101,6 +109,8 @@ if (!defined $toptabs) {
if (!defined $topactions) {
$topactions = $basetopactions;
}
+
+ require RT::URI::freeside;
# Now let callbacks add their extra tabs
$m->comp('/Elements/Callback',
diff --git a/rt/html/Elements/TicketList b/rt/html/Elements/TicketList
index 593a77bc9..4195d6320 100644
--- a/rt/html/Elements/TicketList
+++ b/rt/html/Elements/TicketList
@@ -2,7 +2,7 @@
%#
%# COPYRIGHT:
%#
-%# This software is Copyright (c) 1996-2007 Best Practical Solutions, LLC
+%# This software is Copyright (c) 1996-2005 Best Practical Solutions, LLC
%# <jesse@bestpractical.com>
%#
%# (Except where explicitly superseded by other copyright notices)
@@ -22,9 +22,7 @@
%#
%# 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/copyleft/gpl.html.
+%# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
%#
%#
%# CONTRIBUTION SUBMISSION POLICY:
@@ -45,7 +43,7 @@
%# those contributions and any derivatives thereof.
%#
%# END BPS TAGGED BLOCK }}}
-<table border="0" cellspacing="0" cellpadding="1" width="100%">
+<TABLE BORDER=0 cellspacing=0 cellpadding=1 WIDTH=100%>
% if ($ShowHeader) {
<& /Elements/CollectionAsTable/Header,
@@ -64,12 +62,14 @@
% my $i;
% while (my $record = $Collection->Next) {
% $i++;
-% # Every ten rows, flush the buffer and put something on the page.
-% $m->flush_buffer() unless ($i % 10);
+% # Every $RT::MyTicketsLength or ten rows, flush the buffer and put something
+% # on the page.
+% my $flushrows = $RT::MyTicketsLength || 10;
+% $m->flush_buffer() unless ($i % $flushrows);
<& /Elements/CollectionAsTable/Row, Format => \@Format, i => $i, record => $record, maxitems => $maxitems &>
% }
-</table>
+</TABLE>
% if ($Rows && $ShowNavigation) {
<hr>
@@ -77,9 +77,7 @@
% if (($TotalFound % $Rows) == 0) {
% $oddRows = 0;
% } else { $oddRows = 1; }
-% my $pages = int($TotalFound/$Rows)+$oddRows;
-% $pages = 1 if $pages < 1;
-<&|/l, $Page, $pages &>Page [_1] of [_2]</&>
+<&|/l, $Page, int($TotalFound/$Rows)+$oddRows&>Page [_1] of [_2]</&>
<%perl>
my $prev = $m->comp(
@@ -102,27 +100,18 @@ my $next = $m->comp(
);
</%perl>
% if ($Page > 1) {
-<a href="<%$BaseURL%><%$prev%>"><&|/l&>Previous Page</&></a>
+<A href="<%$BaseURL%><%$prev%>"><&|/l&>Previous Page</&></a>
% }
% if (($Page * $Rows) < $TotalFound) {
-<a href="<%$BaseURL%><%$next%>"><&|/l&>Next Page</&></a>
+<A href="<%$BaseURL%><%$next%>"><&|/l&>Next Page</&></a>
% }
% }
<%INIT>
my $maxitems = 0;
$Format ||= $RT::DefaultSearchResultFormat;
-
-# DisplayFormat lets us use a "temporary" format for display, while
-# still using our original format for next/prev page links.
-# bulk update uses this feature to add checkboxes
-
-
-$DisplayFormat ||= $Format;
-
# Scrub the html of the format string to remove any potential nasties.
$Format = $m->comp('/Elements/ScrubHTML', Content => $Format);
-$DisplayFormat = $m->comp('/Elements/ScrubHTML', Content => $DisplayFormat);
unless ($Collection) {
@@ -130,13 +119,13 @@ unless ($Collection) {
$Collection->FromSQL($Query);
}
-my (@Format) = $m->comp('/Elements/CollectionAsTable/ParseFormat', Format => $DisplayFormat);
+my (@Format) = $m->comp('/Elements/CollectionAsTable/ParseFormat', Format => $Format);
# Find the maximum number of items in any row, so we can pad the table.
my $item = 0;
foreach my $col (@Format) {
$item++;
- if ( $col->{title} && ($col->{title} eq 'NEWLINE') ) {
+ if ( $col->{title} eq 'NEWLINE' ) {
$item = 0;
}
else {
@@ -144,20 +133,10 @@ foreach my $col (@Format) {
}
}
-if ($OrderBy =~ /\|/) {
- # Multiple Sorts
- my @OrderBy = split /\|/,$OrderBy;
- my @Order = split /\|/,$Order;
- $Collection->OrderByCols(
- map { { FIELD => $OrderBy[$_], ORDER => $Order[$_] } } ( 0
- .. $#OrderBy ) );;
-} else {
- $Collection->OrderBy(FIELD => $OrderBy, ORDER => $Order);
-}
+$Collection->OrderBy(FIELD => $OrderBy, ORDER => $Order);
$Collection->RowsPerPage($Rows) if ($Rows);
-$Page = 1 unless $Page > 0; # workaround problems with Page = '' or undef
-$Collection->GotoPage( $Page - 1 ); # SB uses page 0 as the first page
+$Collection->GotoPage($Page-1); # SB uses page 0 as the first page
my $TotalFound = $Collection->CountAll();
</%INIT>
@@ -172,7 +151,6 @@ $Order => undef
$OrderBy => undef
$BaseURL => undef
$Format => $RT::DefaultSearchResultFormat
-$DisplayFormat => undef
$ShowNavigation => 1
$ShowHeader => 1
</%ARGS>
diff --git a/rt/html/Elements/TitleBoxStart b/rt/html/Elements/TitleBoxStart
index ba24fd92e..d98fe2744 100644
--- a/rt/html/Elements/TitleBoxStart
+++ b/rt/html/Elements/TitleBoxStart
@@ -2,7 +2,7 @@
%#
%# COPYRIGHT:
%#
-%# This software is Copyright (c) 1996-2007 Best Practical Solutions, LLC
+%# This software is Copyright (c) 1996-2005 Best Practical Solutions, LLC
%# <jesse@bestpractical.com>
%#
%# (Except where explicitly superseded by other copyright notices)
@@ -22,9 +22,7 @@
%#
%# 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/copyleft/gpl.html.
+%# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
%#
%#
%# CONTRIBUTION SUBMISSION POLICY:
@@ -45,7 +43,46 @@
%# those contributions and any derivatives thereof.
%#
%# END BPS TAGGED BLOCK }}}
+<TABLE CLASS="box <%$class|n%>"
+ BGCOLOR="<%$color%>"
+ CELLSPACING=0
+ BORDER=0
+ WIDTH="<%$width%>"
+ CELLPADDING="0">
+
+ <TR>
+ <TH
+ <%$color && "style=\"color: $color;\""|n%>
+ <%$class ? "class=\"$class\"" : "class=\"titlebox\""|n%>>
+ <span class="titleboxclose">
+ <a href="#" onClick="hideshow('<%$id%>')">X</A></span>&nbsp;
+ <span class="titleboxtitle">
+ <b><% $title_href && "<A $title_class HREF=\"$title_href\">"|n%><%$title |n %><% $title_href && "</A>" |n%></b>
+ </span>
+ </TH>
+ <TH
+ <%$color && "style=\"color: $color;\""|n%>
+ <%$class ? "class=\"$class\"": "class=\"titleboxright\""|n%>>
+ <span class="titleboxright"><%$titleright ? $titleright : '&nbsp;' |n %></span>
+ </TH>
+ </TR>
+ <tr id="element-<%$id%>">
+ <td bgcolor="<%$contentbg%>" colspan="3" class="<%defined($bodyclass) ? $bodyclass : $class|n%>">
+<%ARGS>
+$width => "100%"
+$class => undef
+$bodyclass => undef
+$title_href => undef
+$title => undef
+$title_class => ''
+
+$titleright_href => undef
+$titleright => undef
+$contentbg => "#d4d4d4"
+$color => "#336699"
+</%ARGS>
<%init>
-# For compatibility with 3.4
-$m->comp('/Widgets/TitleBoxStart', %ARGS );
+my $id = rand(2000);
+
+$title_class = "CLASS=\"$title_class\"" if $title_class;
</%init>
diff --git a/rt/html/Elements/ViewUser b/rt/html/Elements/ViewUser
deleted file mode 100644
index 657272496..000000000
--- a/rt/html/Elements/ViewUser
+++ /dev/null
@@ -1,51 +0,0 @@
-%# BEGIN LICENSE BLOCK
-%#
-%# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com>
-%#
-%# (Except where explictly superceded by other copyright notices)
-%#
-%# 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.
-%#
-%# Unless otherwise specified, all modifications, corrections or
-%# extensions to this work which alter its source code become the
-%# property of Best Practical Solutions, LLC when submitted for
-%# inclusion in the work.
-%#
-%#
-%# END LICENSE BLOCK
-<& /Elements/TitleBoxStart,
- title => "<a class='inverse' href=\"$RT::WebPath/Search/Listing.html?LimitRequestorById=1&IdOfRequestor=".$User->id."\">".loc("Tickets from [_1]", $name)."</a>",
- titleright=> "<a class='inverse' href=\"$RT::WebPath/EditUserComments.html?id=".$User->id."\">".loc("Comments about [_1]", $name)."</a>" &>
-<TABLE WIDTH="100%">
-<tr>
-<td halign=left valign=top>
-%while (my $w=$tickets->Next) {
-<%$w->Id%>: <a href="<%$RT::WebPath%>/Ticket/Display.html?id=<%$w->id%>"><%$w->Subject%></a> (<%$w->Status%>)<BR>
-%}
-</td>
-<td align=right valign=top>
- <% ($User->Comments || loc("No comment entered about this user")) %>
-</tr>
-</table>
-<& /Elements/TitleBoxEnd &>
-
-<%ARGS>
-$User=>undef
-</%ARGS>
-
-<%INIT>
-my $name=$User->RealName || $User->EmailAddress;
-
-my $tickets = new RT::Tickets($session{'CurrentUser'});
-$tickets->LimitWatcher(TYPE => 'Requestor', VALUE => $User->EmailAddress);
-
-
-</%INIT>
diff --git a/rt/html/NoAuth/images/back_home.gif b/rt/html/NoAuth/images/back_home.gif
deleted file mode 100644
index 40b19c153..000000000
--- a/rt/html/NoAuth/images/back_home.gif
+++ /dev/null
Binary files differ
diff --git a/rt/html/NoAuth/images/head_requestracker.gif b/rt/html/NoAuth/images/head_requestracker.gif
deleted file mode 100644
index 73315e918..000000000
--- a/rt/html/NoAuth/images/head_requestracker.gif
+++ /dev/null
Binary files differ
diff --git a/rt/html/NoAuth/images/rt.jpg b/rt/html/NoAuth/images/rt.jpg
deleted file mode 100644
index a137a932b..000000000
--- a/rt/html/NoAuth/images/rt.jpg
+++ /dev/null
Binary files differ
diff --git a/rt/html/NoAuth/images/small-logo.png b/rt/html/NoAuth/images/small-logo.png
new file mode 100644
index 000000000..1e415e6d8
--- /dev/null
+++ b/rt/html/NoAuth/images/small-logo.png
Binary files differ
diff --git a/rt/html/NoAuth/images/spacer.gif b/rt/html/NoAuth/images/spacer.gif
deleted file mode 100644
index 5bfd67a2d..000000000
--- a/rt/html/NoAuth/images/spacer.gif
+++ /dev/null
Binary files differ
diff --git a/rt/html/NoAuth/images/squares_blue.gif b/rt/html/NoAuth/images/squares_blue.gif
deleted file mode 100644
index a28da5ce1..000000000
--- a/rt/html/NoAuth/images/squares_blue.gif
+++ /dev/null
Binary files differ
diff --git a/rt/html/NoAuth/webrt.css b/rt/html/NoAuth/webrt.css
index 7fa2f83f8..5da0f8310 100644
--- a/rt/html/NoAuth/webrt.css
+++ b/rt/html/NoAuth/webrt.css
@@ -1,3 +1,4 @@
+/*
%# BEGIN BPS TAGGED BLOCK {{{
%#
%# COPYRIGHT:
@@ -43,36 +44,45 @@
%# those contributions and any derivatives thereof.
%#
%# END BPS TAGGED BLOCK }}}
-SPAN.nav { font-family: Verdana, Arial, Helvetica, sans-serif;
+*/
+
+/* * {
+ font-family: Arial, Verdana, Helvetica, sans-serif;
+ font-size: 1.2em;
+} */
+
+SPAN.nav { font-family: Arial, Verdana, Helvetica, sans-serif;
font-size: 12px;
color: #FFFFFF;
text-decoration: none;
white-space: nowrap}
.nav2 { font-size: 10px;
white-space: nowrap}
-.nav { font-family: Verdana, Arial, Helvetica, sans-serif;
+.nav { font-family: Arial, Verdana, Helvetica, sans-serif;
font-size: 13px;
- font-weight: normal;
+ font-weight: bold;
color: #FFFFFF;
text-decoration: none;
white-space: nowrap}
-.currentnav { font-family: Verdana, Arial, Helvetica, sans-serif;
+.currentnav { font-family: Arial, Verdana, Helvetica, sans-serif;
font-size: 13px;
font-weight: bold;
color: #FFFF66;
text-decoration: none;
white-space: nowrap}
-.topnav { font-family: Verdana, Arial, Helvetica, sans-serif;
+.topnav { font-family: Arial, Verdana, Helvetica, sans-serif;
font-size: 16px;
font-weight: normal;
color: #FFFFFF;
text-decoration: none;
white-space: nowrap}
+/*
%# .topnav is the original RT class for the sidebar navigation tabs.
%# Font-sizing by level depth was originally hard-coded into Elements/Menu.
%# This modification sets a different class name for each level, allowing
%# style sheet control over the formats.
+*/
a.topnav-0 { font-family: Verdana, Arial, Helvetica, sans-serif;
font-size: 16px;
@@ -111,112 +121,114 @@ a.topnav-5 { font-family: Verdana, Arial, Helvetica, sans-serif;
text-decoration: none;
white-space: nowrap}
li.topnav-0-minor {
- border-top: solid #999999 1px;
+ border-top: solid #777777 1px;
padding-top: .1em;
margin-top: .5em;
}
li.topnav-1-minor {
- border-top: solid #999999 1px;
+ border-top: solid #777777 1px;
padding-top: .1em;
margin-top: .5em;
}
li.topnav-2-minor {
- border-top: solid #999999 1px;
+ border-top: solid #777777 1px;
padding-top: .1em;
margin-top: .5em;
}
li.topnav-3-minor {
- border-top: solid #999999 1px;
+ border-top: solid #777777 1px;
padding-top: .1em;
margin-top: .5em;
}
li.topnav-4-minor {
- border-top: solid #999999 1px;
+ border-top: solid #777777 1px;
padding-top: .1em;
margin-top: .5em;
}
li.topnav-5-minor {
- border-top: solid #999999 1px;
+ border-top: solid #777777 1px;
padding-top: .1em;
margin-top: .5em;
}
li.topnav-0-major {
- border-bottom: solid white 1px;
+ border-bottom: solid black 1px;
padding-top: .25em;
padding-bottom: .5em;
}
li.topnav-1-major {
- border-bottom: solid white 1px;
+ border-bottom: solid black 1px;
padding-top: .25em;
padding-bottom: .5em;
}
li.topnav-2-major {
- border-bottom: solid white 1px;
+ border-bottom: solid black 1px;
padding-top: .25em;
padding-bottom: .5em;
}
li.topnav-3-major {
- border-bottom: solid white 1px;
+ border-bottom: solid black 1px;
padding-top: .25em;
padding-bottom: .5em;
}
li.topnav-4-major {
- border-bottom: solid white 1px;
+ border-bottom: solid black 1px;
padding-top: .25em;
padding-bottom: .5em;
}
li.topnav-5-major {
- border-bottom: solid white 1px;
+ border-bottom: solid black 1px;
padding-top: .25em;
padding-bottom: .5em;
}
-.currenttopnav { font-family: Verdana, Arial, Helvetica, sans-serif;
+.currenttopnav { font-family: Arial, Verdana, Helvetica, sans-serif;
font-size: 16px;
font-weight: bold;
- color: #FFFF66;
+ color: #ffffff; background-color: #7e0079;
text-decoration: none;
white-space: nowrap}
+/*
%# .currenttopnav is the original RT class for the sidebar navigation tabs.
%# Font-sizing by level depth was originally hard-coded into Elements/Menu.
%# This modification sets a different class name for each level, allowing
%# style sheet control over the formats
+*/
a.currenttopnav-0 { font-family: Verdana, Arial, Helvetica, sans-serif;
font-size: 16px;
font-weight: bold;
- color: #FFFF66;
+ color: #ffffff; background-color: #7e0079;
text-decoration: none;
white-space: nowrap}
a.currenttopnav-1 { font-family: Verdana, Arial, Helvetica, sans-serif;
font-size: 14px;
font-weight: bold;
- color: #FFFF66;
+ color: #ffffff; background-color: #7e0079;
text-decoration: none;
white-space: nowrap}
a.currenttopnav-2 { font-family: Verdana, Arial, Helvetica, sans-serif;
font-size: 12px;
font-weight: normal;
- color: #FFFF66;
+ color: #ffffff; background-color: #7e0079;
text-decoration: none;
white-space: nowrap}
a.currenttopnav-3 { font-family: Verdana, Arial, Helvetica, sans-serif;
font-size: 11px;
font-weight: normal;
- color: #FFFF66;
+ color: #ffffff; background-color: #7e0079;
text-decoration: none;
white-space: nowrap}
a.currenttopnav-4 { font-family: Verdana, Arial, Helvetica, sans-serif;
font-size: 11px;
font-weight: normal;
- color: #FFFF66;
+ color: #ffffff; background-color: #7e0079;
text-decoration: none;
white-space: nowrap}
a.currenttopnav-5 { font-family: Verdana, Arial, Helvetica, sans-serif;
font-size: 11px;
font-weight: normal;
- color: #FFFF66;
+ color: #ffffff; background-color: #7e0079;
text-decoration: none;
white-space: nowrap}
li.currenttopnav-0-minor {
@@ -225,73 +237,73 @@ li.currenttopnav-0-minor {
margin-top: .5em;
}
li.currenttopnav-1-minor {
- border-top: solid #999999 1px;
+ border-top: solid #777777 1px;
padding-top: .1em;
margin-top: .5em;
}
li.currenttopnav-2-minor {
- border-top: solid #999999 1px;
+ border-top: solid #777777 1px;
padding-top: .1em;
margin-top: .5em;
}
li.currenttopnav-3-minor {
- border-top: solid #999999 1px;
+ border-top: solid #777777 1px;
padding-top: .1em;
margin-top: .5em;
}
li.currenttopnav-4-minor {
- border-top: solid #999999 1px;
+ border-top: solid #777777 1px;
padding-top: .1em;
margin-top: .5em;
}
li.currenttopnav-5-minor {
- border-top: solid #999999 1px;
+ border-top: solid #777777 1px;
padding-top: .1em;
margin-top: .5em;
}
li.currenttopnav-0-major {
- border-bottom: solid white 1px;
+ border-bottom: solid black 1px;
padding-top: .25em;
padding-bottom: .5em;
}
li.currenttopnav-1-major {
- border-bottom: solid white 1px;
+ border-bottom: solid black 1px;
padding-top: .25em;
padding-bottom: .5em;
}
li.currenttopnav-2-major {
- border-bottom: solid white 1px;
+ border-bottom: solid black 1px;
padding-top: .25em;
padding-bottom: .5em;
}
li.currenttopnav-3-major {
- border-bottom: solid white 1px;
+ border-bottom: solid black 1px;
padding-top: .25em;
padding-bottom: .5em;
}
li.currenttopnav-4-major {
- border-bottom: solid white 1px;
+ border-bottom: solid black 1px;
padding-top: .25em;
padding-bottom: .5em;
}
li.currenttopnav-5-major {
- border-bottom: solid white 1px;
+ border-bottom: solid black 1px;
padding-top: .25em;
padding-bottom: .5em;
}
-.topactions { font-family: Verdana, Arial, Helvetica, sans-serif;
+.topactions { font-family: Arial, Verdana, Helvetica, sans-serif;
font-size: 10px;
color: #FFFFFF;
text-decoration: none;
white-space: nowrap}
-.subnav { font-family: Verdana, Arial, Helvetica, sans-serif;
+.subnav { font-family: Arial, Verdana, Helvetica, sans-serif;
font-size: 11px;
font-weight: normal;
color: #FFFFFF;
text-decoration: none;
white-space: nowrap}
-.currentsubnav { font-family: Verdana, Arial, Helvetica, sans-serif;
+.currentsubnav { font-family: Arial, Verdana, Helvetica, sans-serif;
font-size: 11px;
font-weight: bold;
color: #FFFF66;
@@ -307,12 +319,14 @@ li.currenttopnav-5-major {
vertical-align: top;
text-align: left;
}
-.blue { background-color: #4682B4;
+.blue {
+ background-color: #4682B4;
+/* %# background-color: #eeeeee; */
background-position: left top;
vertical-align: top;
text-align: left;
}
-%# Actually the "topactions" section
+/* %# Actually the "topactions" section */
.blueright { background-color: #4682B4;
background-position: left top;
vertical-align: top;
@@ -324,12 +338,123 @@ li.currenttopnav-5-major {
vertical-align: top;
text-align: left;
}
-.darkblue { background-color: #000080;
+.darkblue {
+ background-color: #000080;
+ background-position: left top;
+ vertical-align: top;
+ text-align: left;
+ }
+.darkblueright {
+ background-color: #000080;
+ background-position: left top;
+ vertical-align: top;
+ text-align: right;
+ }
+.lightgray {
+ background-color: #eeeeee;
+ background-position: left top;
+ vertical-align: top;
+ text-align: left;
+ }
+.lightgrayright {
+ background-color: #eeeeee;
+ background-position: left top;
+ vertical-align: top;
+ text-align: right;
+ }
+.black {
+ background-color: #000000;
+ color: #ffffff;
+ background-position: left top;
+ vertical-align: top;
+ text-align: left;
+ }
+.blackright {
+ background-color: #000000;
+ color: #ffffff;
+ background-position: left top;
+ vertical-align: center;
+ text-align: right;
+ font-size:16px;
+ padding-right:4px
+ }
+
+input.fsblackbutton {
+ background-color:#333333;
+ color: #ffffff;
+ border:1px solid;
+ border-top-color:#cccccc;
+ border-left-color:#cccccc;
+ border-right-color:#aaaaaa;
+ border-bottom-color:#aaaaaa;
+ font-family: Arial, Verdana, Helvetica, sans-serif;
+ font-weight:bold;
+ padding-left:12px;
+ padding-right:12px;
+ overflow:visible;
+ filter:progid:DXImageTransform.Microsoft.Gradient(GradientType=0,StartColorStr='#ff333333',EndColorStr='#ff666666')
+}
+
+input.fsblackbuttonselected {
+ background-color:#7e0079;
+ color: #ffffff;
+ border:1px solid;
+ border-top-color:#cccccc;
+ border-left-color:#cccccc;
+ border-right-color:#aaaaaa;
+ border-bottom-color:#aaaaaa;
+ font-family: Arial, Verdana, Helvetica, sans-serif;
+ font-weight:bold;
+ padding-left:12px;
+ padding-right:12px;
+ overflow:visible;
+ filter:progid:DXImageTransform.Microsoft.Gradient(GradientType=0,StartColorStr='#ff330033',EndColorStr='#ff7e0079')
+}
+
+.mediumgray {
+ background-color: #cccccc;
background-position: left top;
vertical-align: top;
text-align: left;
}
-.darkblueright { background-color: #000080;
+.mediumgrayright {
+ background-color: #cccccc;
+ background-position: left top;
+ vertical-align: top;
+ text-align: right;
+ }
+.darkmediumgray {
+ background-color: #aaaaaa;
+ background-position: left top;
+ vertical-align: top;
+ text-align: left;
+ }
+.darkmediumgrayright {
+ background-color: #aaaaaa;
+ background-position: left top;
+ vertical-align: top;
+ text-align: right;
+ }
+.bggray {
+ background-color: #e8e8e8;
+ background-position: left top;
+ vertical-align: top;
+ text-align: left;
+ }
+.bggrayright {
+ background-color: #e8e8e8;
+ background-position: left top;
+ vertical-align: top;
+ text-align: right;
+ }
+.white {
+ background-color: #ffffff;
+ background-position: left top;
+ vertical-align: top;
+ text-align: left;
+ }
+.whiteright {
+ background-color: #ffffff;
background-position: left top;
vertical-align: top;
text-align: right;
@@ -351,26 +476,26 @@ div.downloadattachment {
}
-td { font-family: Verdana, Arial, Helvetica, sans-serif;
- font-size: 11px;
+td { font-family: Arial, Verdana, Helvetica, sans-serif;
+ font-size: 12px;
background-position: left top;
}
.black { background-color: #000000;
background-position: left top;
}
-span.rtname { font-family: Verdana, Arial, Helvetica, sans-serif;
+span.rtname { font-family: Arial, Verdana, Helvetica, sans-serif;
font-size: 18px;
font-weight: normal;
color: #ffffff}
-span.title { font-family: Verdana, Arial, Helvetica, sans-serif;
+span.title { font-family: Arial, Verdana, Helvetica, sans-serif;
font-size: 20px;
font-weight: bold;
color: #ffffff}
-.header { font-family: Verdana, Arial, Helvetica, sans-serif;
+.header { font-family: Arial, Verdana, Helvetica, sans-serif;
font-size: 12px;
font-weight: bold;
color: #0066CC}
-.subheader { font-family: Verdana, Arial, Helvetica, sans-serif;
+.subheader { font-family: Arial, Verdana, Helvetica, sans-serif;
font-size: 11px;
font-weight: bold;
color: #0066CC }
@@ -381,9 +506,9 @@ span.title { font-family: Verdana, Arial, Helvetica, sans-serif;
.labeltop { font-weight: normal;
text-align: right;
vertical-align: top }
-.productnav { font-family: Verdana, Arial, Helvetica, sans-serif;
+.productnav { font-family: Arial, Verdana, Helvetica, sans-serif;
font-size: 11px;
- color: #000000;
+ color: #FFFFFF;
text-align: center;
vertical-align: middle;
text-decoration: none}
@@ -405,6 +530,7 @@ TD.mainbody {
padding-right: 1em;
margin-left: 1em;
margin-right: 1em;
+ background-color: #e8e8e8;
}
td.boxcontainer + td.boxcontainer {
@@ -447,7 +573,7 @@ TD.titlebox {
SPAN.message {
font-size: 100%;
- font-family: Verdana, Arial, Helvetica, sans-serif;
+ font-family: Arial, Verdana, Helvetica, sans-serif;
}
@@ -490,7 +616,7 @@ DIV.endmatter { margin-left: -7% }
}
-A { font-weight: bold; color: #000000;
+A { font-weight: bold; color: #000000
}
.currenttab { color: #ffffff;}
@@ -504,8 +630,9 @@ A:link IMG, A:visited IMG { border-style: none }
a:focus {text-decoration: underline }
A IMG { color: white } /* The only way to hide the border in NS 4.x */
-a:link { text-decoration: none}
-a:visited { text-decoration: none}
+/* a:link { text-decoration: none} */
+/* a:visited { text-decoration: none} */
+
a:hover { text-decoration: underline}
/* a:focus { background-color: #ccccee } */
@@ -518,7 +645,9 @@ SPAN.date { font-size: 0.8em }
span.title { font-size: 1.6em;
vertical-align: middle;
- color: #ffffff;}
+/* %# color: #ffffff; */
+ color: #000000;
+ }
span.productname { font-size: 2em;
color: #0066cc;}
SPAN.titleboxtitle, SPAN.titleboxclose {
@@ -615,6 +744,7 @@ textarea.messagebox {
width: 100%;
}
+/*
%# Provide a callback for adding/modifying the style sheet.
%# http://www.w3.org/TR/REC-CSS1 - section 3.2, says:
%# "latter specified rule wins"
@@ -626,3 +756,4 @@ inherit => undef
$r->content_type('text/css');
#$r->headers_out->{'Expires'} = '+30m';
</%init>
+*/
diff --git a/rt/html/RTx/Statistics/CallsMultiQueue/Elements/Chart b/rt/html/RTx/Statistics/CallsMultiQueue/Elements/Chart
new file mode 100755
index 000000000..02a183b2c
--- /dev/null
+++ b/rt/html/RTx/Statistics/CallsMultiQueue/Elements/Chart
@@ -0,0 +1,39 @@
+<%perl>
+$r->content_type("image/$format");
+print $graph->plot(\@data)->$format();
+$m->abort();
+</%perl>
+<em><&|/l, $#data+1&>[_1] Plot Elements</&></em><p>
+% foreach my $value (@data) {
+<% $value %><p>
+% }
+<em><&|/l&>x_labels</&>:</em><p>
+<% $ARGS{x_labels} %>
+<p>
+<em><&|/l&>legend</&>:</em><p>
+<% $ARGS{set_legend} %>
+<p>
+<em><&|/l, (keys %ARGS) - 2&>[_1] data sets</&>:</em><p>
+
+% for (1..(scalar keys %ARGS)-2) {
+<% $_ %> <% $ARGS{"data$_"} %><p>
+% }
+
+<%INIT>
+use GD::Graph::lines;
+
+my @data;
+my $graph = GD::Graph::lines->new($Statistics::GraphWidth,$Statistics::GraphHeight);
+$graph->set(export_format => "png",
+ x_label => 'Day of Week',
+ y_label => 'Tickets per day');
+$graph->set_legend(split /,/ , $ARGS{set_legend});
+my $format = $graph->export_format;
+push @data, [split /,/ , $ARGS{x_labels}];
+for (1..((scalar keys %ARGS)-2)) {
+ push @data, [split /,/ , $ARGS{"data".$_}];
+}
+
+</%INIT>
+<%ARGS>
+</%ARGS>
diff --git a/rt/html/RTx/Statistics/CallsMultiQueue/index.html b/rt/html/RTx/Statistics/CallsMultiQueue/index.html
new file mode 100755
index 000000000..abf8aa74a
--- /dev/null
+++ b/rt/html/RTx/Statistics/CallsMultiQueue/index.html
@@ -0,0 +1,330 @@
+<& /Elements/Header, Title => loc('Tickets per day in Multiple queues') &>
+<& /RTx/Statistics/Elements/Tabs, Title => loc('Tickets per day in Multiple Queues by status') &>
+
+<h3>Description</h3>
+<p>This chart shows details of tickets per day by their status. You can select multiple queues to display at the same time, but only one status. You can chose any of the defined status values.
+There is also the option to display all available queues at the same time.
+The default display shows tickets resolved in your default queue (General unless altered locally).
+The line chart below shows the same information in a graphical form.
+
+<br />
+
+<form method="POST" action="index.html">
+
+%# Build Legend
+% my @legend;
+% for (sort keys %queues_to_show) {
+% push @legend, $_;
+% }
+
+%my $title = "Tickets with Status $status in " . join(', ', @queues) . ", per day from " .
+% Statistics::FormatDate($Statistics::PerDayDateFormat, $dates[0]) . " through " .
+% Statistics::FormatDate($Statistics::PerDayDateFormat, $dates[$#dates-1]);
+
+<& /Elements/TitleBoxStart, title => $title, title_href => "/RTx/Statistics/OpenStalled/index.html?$QueryString"&>
+<TABLE BORDER=0 cellspacing=0 cellpadding=1 WIDTH="100%">
+% if ($ShowHeader) {
+<& /RTx/Statistics/Elements/CollectionAsTable/Header,
+ Format => \@RowFormat,
+ FormatString => $RowFormat,
+ AllowSorting => $AllowSorting,
+ Order => $Order,
+ Query => undef,
+ Rows => $Rows,
+ Page => $Page,
+ OrderBy => $OrderBy ,
+ BaseURL => $BaseURL,
+ maxitems => $maxitems &>
+% }
+% my $line = 0;
+% LINE: for my $d (0..$#dates) {
+% if ($d == $#dates ){
+% next LINE;
+% }
+% $line++;
+% my $x = 1;
+% $values{Statistics_Date} = Statistics::FormatDate($dateformat, $dates[$d]);
+% my $row_total=0;
+% foreach my $q (sort keys %queues_to_show) {
+% my $tix = new RT::Tickets($session{'CurrentUser'});
+% if ($status eq "resolved") {
+% $tix->LimitStatus(VALUE => $status);
+% $tix->LimitResolved(VALUE => $dates[$d]->ISO, OPERATOR => ">=");
+% if ($dates[$d+1]) {
+% $tix->LimitResolved(VALUE => $dates[$d+1]->ISO, OPERATOR => "<=");
+% }
+% }
+% elsif ($status eq "new") {
+% $tix->LimitCreated(VALUE => $dates[$d]->ISO, OPERATOR => ">=");
+% if ($dates[$d+1]) {
+% $tix->LimitCreated(VALUE => $dates[$d+1]->ISO, OPERATOR => "<=");
+% }
+% }
+% elsif ($status eq "deleted") {
+% $tix->LimitStatus(VALUE => $status);
+% $tix->LimitLastUpdated(VALUE => $dates[$d]->ISO, OPERATOR => ">=");
+% if ($dates[$d+1]) {
+% $tix->LimitLastUpdated(VALUE => $dates[$d+1]->ISO, OPERATOR => "<=");
+% }
+% }
+% elsif ($status eq "stalled") {
+% $tix->LimitStatus(VALUE => $status);
+% $tix->LimitLastUpdated(VALUE => $dates[$d]->ISO, OPERATOR => ">=");
+% if ($dates[$d+1]) {
+% $tix->LimitLastUpdated(VALUE => $dates[$d+1]->ISO, OPERATOR => "<=");
+% }
+% }
+% elsif ($status eq "open") {
+% $tix->LimitStatus(VALUE => $status);
+% $tix->LimitLastUpdated(VALUE => $dates[$d]->ISO, OPERATOR => ">=");
+% if ($dates[$d+1]) {
+% $tix->LimitLastUpdated(VALUE => $dates[$d+1]->ISO, OPERATOR => "<=");
+% }
+% }
+% elsif ($status eq "rejected") {
+% $tix->LimitStatus(VALUE => $status);
+% $tix->LimitLastUpdated(VALUE => $dates[$d]->ISO, OPERATOR => ">=");
+% if ($dates[$d+1]) {
+% $tix->LimitLastUpdated(VALUE => $dates[$d+1]->ISO, OPERATOR => "<=");
+% }
+% }
+% $tix->LimitQueue (VALUE => $q);
+% $values{$q} = $tix->Count;
+% $row_total += $tix->Count;
+% $data[$x++][$d] = $tix->Count;
+% }
+% $values{Statistics_Totals} = $row_total;
+<& /RTx/Statistics/Elements/CollectionAsTable/Row, Format => \@RowFormat, i => $line, record => $record, maxitems => $maxitems &>
+% }
+</table>
+<& /Elements/TitleBoxEnd&>
+
+<hr>
+
+<BR />
+<BR />
+
+<!-- <td>Show:</td>
+ <td COLSPAN=2><SELECT NAME="status">
+% for (qw(resolved new deleted stalled rejected open)) {
+ <OPTION VALUE="<% $_ %>" <% $_ eq $status && "SELECTED" %>>
+ <% loc($_) %></OPTION>
+% }
+--!>
+
+<%perl>
+# Create the graph URL
+my $url = 'Elements/Chart?x_labels=';
+#$url .= join ",", @{ shift @data } . "&";
+for (0..$max) {
+ $url .= $m->interp->apply_escapes($data[0][$_],'u') . ",";
+}
+chop $url;
+$url .= "&";
+shift @data;
+$url .= 'set_legend='.(join ",", @legend)."&";
+for (0..$#data) {
+ $url .= "data".(1+$_)."=". (join ",", @{$data[$_]})."&";
+}
+chop $url;
+</%perl>
+
+<& /RTx/Statistics/Elements/GraphBox, GraphURL => $url &>
+
+<& /RTx/Statistics/Elements/ControlsAsTable/ControlBox,
+ Title => "Change Status, Queues or Dates",
+ ShowDates => 1, sMonth => \$sMonth, sDay => \$sDay, sYear => \$sYear,
+ eMonth => \$eMonth, eDay => \$eDay, eYear => \$eYear,
+ weekends => $weekends,
+ ShowMultiQueues => 1, queues_ref => \@queues,
+ ShowStatus => 1, Status => $status
+ &>
+
+</form>
+
+<a href="<%$RT::WebPath%>/RTx/Statistics/CallsMultiQueue/index.html?<% $QueryString %>"><&|/l&>Bookmarkable link</&></a>
+%# | <a href="<%$RT::WebPath%>/RTx/Statistics/CallsMultiQueue/Results.tsv?<%$QueryString%>"><&|/l&>spreadsheet</&></a>
+<BR>
+<BR>
+
+<%ARGS>
+$status => $Statistics::MultiQueueStatus
+$max => $Statistics::MultiQueueMaxRows
+@queues => @Statistics::MultiQueueQueueList
+$weekends => $Statistics::PerDayWeekends;
+$sMonth=>undef
+$sDay=>undef
+$sYear=>undef
+$eMonth=>undef
+$eDay=>undef
+$eYear=>undef
+$days=>undef
+$dateformat => $Statistics::MultiQueueDateFormat
+$currentMonth=>undef
+
+$AllowSorting => undef
+$Order => undef
+$OrderBy => undef
+$ShowNavigation => 1
+$ShowHeader => 1
+$Rows => 50
+$Page => 1
+$BaseURL => undef
+$AddAllCheck => undef
+</%ARGS>
+
+<%INIT>
+
+use RTx::Statistics;
+use Time::Local;
+my $n = 0;
+my @data = ([]);
+my @dates;
+my @msgs;
+my $selected;
+my $diff;
+my %queues_to_show;
+my $secsPerDay=86400;
+my $sEpoch;
+my $eEpoch;
+my $QueryString;
+my $maxitems;
+my $RowFormat;
+my $BoldRowFormat;
+my %record;
+my %values;
+my $record = \%record;
+
+$record{values} = \%values;
+
+Statistics::DebugClear();
+Statistics::DebugLog("CallsQueueDay/index.html ARGS:\n");
+for my $key (keys %ARGS) {
+ Statistics::DebugLog("ARG{ $key }=" . $ARGS{$key} . "\n");
+}
+
+
+ # Handle the Add All Checkbox
+ if($AddAllCheck eq "on") {
+ $AddAllCheck = undef;
+ undef (@queues);
+ my $q=new RT::Queues($session{'CurrentUser'});
+ $q->UnLimit;
+ while (my $queue=$q->Next) {
+ next if !$queue->CurrentUserHasRight('SeeQueue');
+ push @queues, $queue->Name;
+ }
+ }
+
+ # If the user has the right to see the queue, put it into the map
+ for my $q (@queues) {
+ my $Queueobj = new RT::Queue($session{'CurrentUser'});
+ $Queueobj->Load($q);
+ next if !$Queueobj->CurrentUserHasRight('SeeQueue');
+ $queues_to_show{$q} = 1;
+ }
+
+ $maxitems = (scalar @queues) + 2;
+
+ # Build the format strings
+ $RowFormat = "'__Statistics_Date__'";
+ $BoldRowFormat = "'<B>__Statistics_Date__</B>'";
+ for my $q (@queues) {
+ $RowFormat .= ",'__Statistics_Dynamic__/KEY:$q/TITLE:$q/STYLE:text-align:right;'";
+ $BoldRowFormat .= ",'<B>__Statistics_Dynamic__</B>/KEY:$q/TITLE:$q/STYLE:text-align:right;'";
+ }
+ $RowFormat .= ",'<B>__Statistics_Totals__</B>/STYLE:text-align:right;'";
+ $BoldRowFormat .= ",'<B>__Statistics_Totals__</B>/STYLE:text-align:right;'";
+ # Parse the formats into structures.
+ my (@RowFormat) = $m->comp('/RTx/Statistics/Elements/CollectionAsTable/ParseFormat', Format => $RowFormat);
+ my (@BoldRowFormat) = $m->comp('/RTx/Statistics/Elements/CollectionAsTable/ParseFormat', Format => $BoldRowFormat);
+
+if ($sDay > $Statistics::monthsMaxDay{$sMonth}) {
+ $sDay = $Statistics::monthsMaxDay{$sMonth};
+}
+
+if ($eDay > $Statistics::monthsMaxDay{$eMonth}) {
+ $eDay = $Statistics::monthsMaxDay{$eMonth};
+}
+
+if ($sYear){
+ $sEpoch = timelocal(0, 0, 0, $sDay, $sMonth, $sYear-1900);
+}
+if ($eYear){
+Statistics::DebugLog("eMonth = " . $eMonth . "\n");
+ $eEpoch = timelocal(0, 0, 0, $eDay, $eMonth, $eYear-1900);
+} else {
+ # This case happens when the page is first loaded
+ my @local = localtime(time);
+ ($eDay, $eMonth, $eYear) = ($local[3], $local[4], $local[5]);
+ $eYear += 1900;
+ $eEpoch = timelocal(0, 0, 0, $local[3], $local[4], $local[5], $local[6], $local[7], $local[8]);
+Statistics::DebugLog("Setting eEpoch=$eEpoch from current time.\n");
+}
+
+if (($eEpoch < $sEpoch) || ($sEpoch == 0)) {
+ # We have an end, but not a start, or, overlapping.
+
+ # if $currentMonth is set, just set the day to 1
+ if($currentMonth) {
+ # set start vars from end, but with day set to 1
+ (undef, undef, undef, $sDay, $sMonth, $sYear) = localtime($eEpoch);
+ $sDay=1;
+ $sEpoch = timelocal(0, 0, 0, $sDay, $sMonth, $sYear);
+ } else {
+ # If the user has specified how many days back to go, use that,
+ # If not, set start to configured default period before end
+ if(defined $days) {
+ $sEpoch = $eEpoch - ($days * $Statistics::secsPerDay);
+ } else {
+ $sEpoch = $eEpoch - ($Statistics::PerDayPeriod * $Statistics::secsPerDay);
+ }
+ (undef, undef, undef, $sDay, $sMonth, $sYear) = localtime($sEpoch);
+ }
+ $sYear += 1900;
+}
+
+# Compute days to chart.
+# The +1 is because we need to generate one more date. If the user
+# selected a 10 day range, we need to generate 11 days.
+$diff = int(($eEpoch - $sEpoch + $Statistics::secsPerDay - 1) / $Statistics::secsPerDay)+1;
+Statistics::DebugLog("Setting diff=$diff\n");
+
+Statistics::DebugLog("sEpoch=$sEpoch, components=" . join(',', localtime($sEpoch)) . "\n");
+Statistics::DebugLog("eEpoch=$eEpoch, components=" . join(',', localtime($eEpoch)) . "\n");
+
+# Build the new query string
+$QueryString = "queues=" . join("&queues=", @queues);
+$QueryString .= "&sDay=$sDay&sMonth=$sMonth&sYear=$sYear&eDay=$eDay&eMonth=$eMonth&eYear=$eYear&weekends=$weekends";
+
+
+
+
+# Set up the end date to be midnight(morning) of the date after the one the user wanted.
+my $endRange = $eEpoch + $Statistics::secsPerDay;
+$n = 0;
+until ($#dates == $diff) {
+ my $date = new RT::Date($session{CurrentUser});
+ $date->Set(Value=>$endRange - $n, Format => 'unix');
+ # Note: we used to adjust the time to local midnight, but
+ # none of the other date entry fields in RT seem to adjust, so we've stopped.
+ #Statistics::DebugLog("Before adjust to midnight date " . Statistics::FormatDate("%c", $date) . "\n");
+ $n+= $Statistics::secsPerDay;
+ # If we aren't showing weekends and this is one, decrement the number
+ # of days to show and skip to the next date.
+ if(!$weekends and Statistics::RTDateIsWeekend($date)) {$diff--; next;}
+ unshift @dates, $date;
+Statistics::DebugLog("pushing date " . Statistics::FormatDate("%c", $date) . "\n");
+ unshift @{ $data[0] }, Statistics::FormatDate($Statistics::PerDayLabelDateFormat, $date);
+}
+
+# We put an extra day into the lists to cover up till midnight of the next day,
+# But we don't want that to appear in the labels, so pop it off.
+pop( @{ $data[0] } );
+
+my $queue = new RT::Queues($session{CurrentUser});
+$queue->UnLimit;
+
+my $QueueObj = new RT::Queue($session{'CurrentUser'});
+$QueueObj->Load($queue);
+</%INIT>
diff --git a/rt/html/RTx/Statistics/CallsQueueDay/Elements/Chart b/rt/html/RTx/Statistics/CallsQueueDay/Elements/Chart
new file mode 100755
index 000000000..9a3a50574
--- /dev/null
+++ b/rt/html/RTx/Statistics/CallsQueueDay/Elements/Chart
@@ -0,0 +1,29 @@
+<%perl>
+$r->content_type("image/$format");
+print $graph->plot(\@data)->$format();
+$m->abort();
+print $#data+1 . " Elements:<p>";
+for (0..$#data) {
+print $data[$_];
+print "<p>";
+}
+</%perl>
+<%INIT>
+use GD::Graph::lines;
+
+my @data;
+my $graph = GD::Graph::lines->new($Statistics::GraphWidth,$Statistics::GraphHeight);
+$graph->set(export_format => "png",
+ x_label => 'Day of Week',
+ y_label => 'Tickets per Day',
+ x_labels_vertical => 1,
+ );
+my $format = $graph->export_format;
+$graph->set_legend(split /,/ , $ARGS{set_legend});
+push @data, [split /,/ , $ARGS{x_labels}];
+push @data, [split /,/ , $ARGS{data1}];
+push @data, [split /,/ , $ARGS{data2}];
+push @data, [split /,/ , $ARGS{data3}];
+</%INIT>
+<%ARGS>
+</%ARGS>
diff --git a/rt/html/RTx/Statistics/CallsQueueDay/Results.tsv b/rt/html/RTx/Statistics/CallsQueueDay/Results.tsv
new file mode 100644
index 000000000..23f0c699c
--- /dev/null
+++ b/rt/html/RTx/Statistics/CallsQueueDay/Results.tsv
@@ -0,0 +1,191 @@
+%# BEGIN BPS TAGGED BLOCK {{{
+%#
+%# COPYRIGHT:
+%#
+%# This software is Copyright (c) 1996-2005 Best Practical Solutions, LLC
+%# <jesse@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., 675 Mass Ave, Cambridge, MA 02139, USA.
+%#
+%#
+%# 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 }}}
+<%ARGS>
+$Queue => undef
+$weekends => $Statistics::PerDayWeekends;
+$sMonth=>undef
+$sDay=>undef
+$sYear=>undef
+$eMonth=>undef
+$eDay=>undef
+$eYear=>undef
+$days=>undef
+$currentMonth=>undef
+</%ARGS>
+
+<%INIT>
+use RTx::Statistics;
+use Time::Local;
+my @dates;
+my $n = 0;
+my %Totals;
+my $now = new RT::Date($session{CurrentUser});
+my $sEpoch;
+my $eEpoch;
+
+if (!defined $Queue) {
+ $Queue = $Statistics::PerDayQueue;
+}
+
+if ($sDay > $Statistics::monthsMaxDay{$sMonth}) {
+ $sDay = $Statistics::monthsMaxDay{$sMonth};
+}
+
+if ($eDay > $Statistics::monthsMaxDay{$eMonth}) {
+ $eDay = $Statistics::monthsMaxDay{$eMonth};
+}
+
+if ($sYear){
+ $sEpoch = timelocal(0, 0, 0, $sDay, $sMonth, $sYear-1900);
+}
+if ($eYear){
+Statistics::DebugLog("eMonth = " . $eMonth . "\n");
+ $eEpoch = timelocal(0, 0, 0, $eDay, $eMonth, $eYear-1900);
+} else {
+ # This case happens when the page is first loaded
+ my @local = localtime(time);
+ ($eDay, $eMonth, $eYear) = ($local[3], $local[4], $local[5]);
+ $eYear += 1900;
+ $eEpoch = timelocal(0, 0, 0, $local[3], $local[4], $local[5], $local[6], $local[7], $local[8]);
+Statistics::DebugLog("Setting eEpoch=$eEpoch from current time.\n");
+}
+
+if (($eEpoch < $sEpoch) || ($sEpoch == 0)) {
+ # We have an end, but not a start, or, overlapping.
+
+ # if $currentMonth is set, just set the day to 1
+ if($currentMonth) {
+ # set start vars from end, but with day set to 1
+ (undef, undef, undef, $sDay, $sMonth, $sYear) = localtime($eEpoch);
+ $sDay=1;
+ $sEpoch = timelocal(0, 0, 0, $sDay, $sMonth, $sYear);
+ } else {
+ # If the user has specified how many days back to go, use that,
+ # If not, set start to configured default period before end
+ if(defined $days) {
+ $sEpoch = $eEpoch - ($days * $Statistics::secsPerDay);
+ } else {
+ $sEpoch = $eEpoch - ($Statistics::PerDayPeriod * $Statistics::secsPerDay);
+ }
+ (undef, undef, undef, $sDay, $sMonth, $sYear) = localtime($sEpoch);
+ }
+ $sYear += 1900;
+}
+
+# set content type
+$r->content_type('application/vnd.ms-excel');
+
+# Put out some data about the generation of this file
+$m->out("Tickets per day for Queue:\t" . $Queue . "\tGenerated at:\t" . Statistics::FormatDate("%x %X", $now). "\n\n");
+
+
+# Compute days to chart.
+# The +1 is because we need to generate one more date. If the user
+# selected a 10 day range, we need to generate 11 days.
+my $diff = int(($eEpoch - $sEpoch + $Statistics::secsPerDay - 1) / $Statistics::secsPerDay)+1;
+
+# Build array of dates
+my $endRange = $eEpoch + $Statistics::secsPerDay;
+my $QueueObj = new RT::Queue($session{'CurrentUser'});
+$QueueObj->Load($Queue);
+until ($#dates == $diff) {
+ my $date = new RT::Date($session{CurrentUser});
+ $date->Set(Value=>$endRange - $n, Format => 'unix');
+ # Note: we used to adjust the time to local midnight, but
+ # none of the other date entry fields in RT seem to adjust, so we've stopped.
+ #Statistics::DebugLog("Before adjust to midnight date " . Statistics::FormatDate("%c", $date) . "\n");
+ $n+= $Statistics::secsPerDay;
+ # If we aren't showing weekends and this is one, decrement the number
+ # of days to show and skip to the next date.
+ if(!$weekends and Statistics::RTDateIsWeekend($date)) {$diff--; next;}
+ unshift @dates, $date;
+}
+
+# Output header row
+$m->out("Date\tcreate\tresolved\tdeleted\n");
+
+
+LINE: for my $d (0..$#dates) {
+ if ($d == $#dates){
+ next LINE;
+ }
+ my $x = 1;
+ # Output the date for this row
+ $m->out(Statistics::FormatDate($Statistics::PerDayDateFormat, $dates[$d]));
+
+ # output the 3 columns for this row
+ for my $status (qw(created resolved deleted)) {
+ my $tix = new RT::Tickets($session{'CurrentUser'});
+ if ($status eq "created") {
+ $tix->LimitCreated(VALUE => $dates[$d]->ISO, OPERATOR => ">=");
+ if ($dates[$d+1]) {
+ $tix->LimitCreated(VALUE => $dates[$d+1]->ISO, OPERATOR => "<=");
+ }
+ } elsif ($status eq "resolved") {
+ $tix->LimitStatus(VALUE => $status);
+ $tix->LimitResolved(VALUE => $dates[$d]->ISO, OPERATOR => ">=");
+ if ($dates[$d+1]) {
+ $tix->LimitResolved(VALUE => $dates[$d+1]->ISO, OPERATOR => "<=");
+ }
+ } elsif ($status eq "deleted") {
+ $tix->LimitStatus(VALUE => $status);
+ $tix->LimitLastUpdated(VALUE => $dates[$d]->ISO, OPERATOR => ">=");
+ if ($dates[$d+1]) {
+ $tix->LimitLastUpdated(VALUE => $dates[$d+1]->ISO, OPERATOR => "<=");
+ }
+ }
+ $tix->LimitQueue (VALUE => $Queue);
+ $m->out( "\t" . $tix->Count );
+ $Totals{$status} += $tix->Count;
+ }
+ $m->out("\n");
+}
+
+# Output the totals
+$m->out("Totals\t$Totals{created}\t$Totals{resolved}\t$Totals{deleted}\n");
+
+$m->abort();
+</%INIT>
diff --git a/rt/html/RTx/Statistics/CallsQueueDay/index.html b/rt/html/RTx/Statistics/CallsQueueDay/index.html
new file mode 100755
index 000000000..06fc484d1
--- /dev/null
+++ b/rt/html/RTx/Statistics/CallsQueueDay/index.html
@@ -0,0 +1,275 @@
+<& /Elements/Header, Title => loc("Tickets per day in Queue:" . $QueueObj->Name()) &>
+<& /RTx/Statistics/Elements/Tabs, Title => loc("Tickets by status per day in Queue:" . $QueueObj->Name()) &>
+
+<h3>Description</h3>
+<p>This page displays details about tickets in the selected queue over the date range chosen. It shows how many tickets were created on
+each day in the chosen range, and how many of those were either Resolved or Deleted.</p>
+<p>To always show the current month to date, bookmark this <a href="<%$RT::WebPath%>/RTx/Statistics/CallsQueueDay/index.html?currentMonth=1">link</a>, or
+for a spreadsheet, use this <a href="<%$RT::WebPath%>/RTx/Statistics/CallsQueueDay/Results.tsv?currentMonth=1">link</a>.</p>
+
+<form method="POST" action="index.html">
+
+% Statistics::DebugLog("queue name=" . $QueueObj->Name() . "\n");
+
+%my $title = "Ticket counts in " . $QueueObj->Name() . " by status per day from " .
+% Statistics::FormatDate($Statistics::PerDayDateFormat, $dates[0]) . " through " .
+% Statistics::FormatDate($Statistics::PerDayDateFormat, $dates[$#dates-1]);
+<&|/Elements/TitleBox,
+ title => $title,
+ title_href => "/RTx/Statistics/CallsQueueDay/index.html?$QueryString" &>
+<TABLE BORDER=0 cellspacing=0 cellpadding=1 WIDTH=100%>
+% if ($ShowHeader) {
+<& /RTx/Statistics/Elements/CollectionAsTable/Header,
+ Format => \@Format,
+ FormatString => $Format,
+ AllowSorting => $AllowSorting,
+ Order => $Order,
+ Query => undef,
+ Rows => $Rows,
+ Page => $Page,
+ OrderBy => $OrderBy ,
+ BaseURL => $BaseURL,
+ maxitems => $maxitems &>
+% }
+% my $line = 1;
+% LINE: for my $d (0..$#dates) {
+% if ($d == $#dates){
+% next LINE;
+% }
+% my $x = 1;
+% $values{Statistics_Date} = Statistics::FormatDate($Statistics::PerDayDateFormat, $dates[$d]);
+%# NOTE need to handle all status values here....
+% for my $status (qw(created resolved deleted)) {
+% my $tix = new RT::Tickets($session{'CurrentUser'});
+% $tix->LimitQueue (VALUE => $Queue);
+% if ($status eq "created") {
+% $tix->LimitCreated(VALUE => $dates[$d]->ISO, OPERATOR => ">=");
+% if ($dates[$d+1]) {
+% $tix->LimitCreated(VALUE => $dates[$d+1]->ISO, OPERATOR => "<=");
+% }
+% $values{Statistics_Created_Count} = $tix->Count;
+% $Totals{Statistics_Created_Count} += $tix->Count;
+% }
+% elsif ($status eq "resolved") {
+% $tix->LimitStatus(VALUE => $status);
+% $tix->LimitResolved(VALUE => $dates[$d]->ISO, OPERATOR => ">=");
+% if ($dates[$d+1]) {
+% $tix->LimitResolved(VALUE => $dates[$d+1]->ISO, OPERATOR => "<=");
+% }
+% $values{Statistics_Resolved_Count} = $tix->Count;
+% $Totals{Statistics_Resolved_Count} += $tix->Count;
+% }
+% elsif ($status eq "deleted") {
+% $tix->LimitStatus(VALUE => $status);
+% $tix->LimitLastUpdated(VALUE => $dates[$d]->ISO, OPERATOR => ">=");
+% if ($dates[$d+1]) {
+% $tix->LimitLastUpdated(VALUE => $dates[$d+1]->ISO, OPERATOR => "<=");
+% }
+% $values{Statistics_Deleted_Count} = $tix->Count;
+% $Totals{Statistics_Deleted_Count} += $tix->Count;
+% }
+% $data[$x++][$d] = $tix->Count;
+% }
+<& /RTx/Statistics/Elements/CollectionAsTable/Row, Format => \@Format, i => $line, record => $record, maxitems => $maxitems &>
+% $line++;
+% }
+% $values {Statistics_Date} = "Totals";
+% $values {Statistics_Created_Count} = $Totals{Statistics_Created_Count};
+% $values {Statistics_Resolved_Count} = $Totals{Statistics_Resolved_Count};
+% $values {Statistics_Deleted_Count} = $Totals{Statistics_Deleted_Count};
+<& /RTx/Statistics/Elements/CollectionAsTable/Row, Format => \@BoldFormat, i => $line, record => $record, maxitems => $maxitems &>
+</table>
+</&>
+
+<hr>
+
+<BR />
+<BR />
+
+<%perl>
+# Create the graph URL
+my $url= 'Elements/Chart?x_labels=';
+for (1..$diff) {
+ $url .= $data[0][$_] . ",";
+}
+chop $url;
+$url .= "&";
+shift @data;
+for (0..$#data) {
+ $url .= "data".(1+$_)."=".(join ",", @{$data[$_]})."&";
+}
+chop $url;
+$url .= "&set_legend=Created,Resolved,Deleted";
+</%perl>
+
+<& /RTx/Statistics/Elements/GraphBox, GraphURL => $url &>
+
+<& /RTx/Statistics/Elements/ControlsAsTable/ControlBox,
+ Title => "Change Queue or Dates",
+ ShowDates => 1, sMonth => \$sMonth, sDay => \$sDay, sYear => \$sYear,
+ eMonth => \$eMonth, eDay => \$eDay, eYear => \$eYear,
+ weekends => $weekends,
+ ShowSingleQueue => 1, Queue => $Queue
+ &>
+
+</form>
+
+<a href="<%$RT::WebPath%>/RTx/Statistics/CallsQueueDay/index.html?<% $QueryString %>"><&|/l&>Bookmarkable link</&></a> |
+<a href="<%$RT::WebPath%>/RTx/Statistics/CallsQueueDay/Results.tsv?<%$QueryString%>"><&|/l&>spreadsheet</&></a>
+<BR>
+<BR>
+
+
+% Statistics::DebugLog("ref of eMonth is " . ref($eMonth) . "\n");
+% Statistics::DebugInit( $m );
+
+<%ARGS>
+$Queue => undef
+$weekends => $Statistics::PerDayWeekends;
+$sMonth=>undef
+$sDay=>undef
+$sYear=>undef
+$eMonth=>undef
+$eDay=>undef
+$eYear=>undef
+$days=>undef
+$currentMonth=>undef
+
+$AllowSorting => undef
+$Order => undef
+$OrderBy => undef
+$ShowNavigation => 1
+$ShowHeader => 1
+$Rows => 50
+$Page => 1
+$BaseURL => undef
+</%ARGS>
+
+<%INIT>
+use RTx::Statistics;
+use Time::Local;
+my $selected;
+my $n = 0;
+my @data = ([]);
+my @dates;
+my @msgs;
+my $diff;
+my $sEpoch=0;
+my $eEpoch=0;
+my %Totals;
+my $QueryString;
+my $maxitems = 4;
+my %record;
+my %values;
+my $record = \%record;
+
+$record{values} = \%values;
+
+
+# If debugging, set things up and display all the args
+Statistics::DebugClear();
+Statistics::DebugLog("CallsQueueDay/index.html ARGS:\n");
+for my $key (keys %ARGS) {
+ Statistics::DebugLog("ARG{ $key }=" . $ARGS{$key} . "\n");
+}
+
+my $Format = qq{ Statistics_Date,
+ '__Statistics_Created_Count__/STYLE:text-align:right;',
+ '__Statistics_Resolved_Count__/STYLE:text-align:right;',
+ '__Statistics_Deleted_Count__/STYLE:text-align:right;' };
+my $BoldFormat = qq{ '<B>__Statistics_Date__</B>',
+ '<B>__Statistics_Created_Count__</B>/STYLE:text-align:right;',
+ '<B>__Statistics_Resolved_Count__</B>/STYLE:text-align:right;',
+ '<B>__Statistics_Deleted_Count__</B>/STYLE:text-align:right;' };
+my (@Format) = $m->comp('/RTx/Statistics/Elements/CollectionAsTable/ParseFormat', Format => $Format);
+my (@BoldFormat) = $m->comp('/RTx/Statistics/Elements/CollectionAsTable/ParseFormat', Format => $BoldFormat);
+Statistics::DebugLog("CallsQueueDay/index.html Format array=" . join(',', @Format) . "\n");
+
+if (!defined $Queue) {
+ my $QueueObj = new RT::Queue($session{'CurrentUser'});
+ $QueueObj->Load($Statistics::PerDayQueue);
+ $Queue = $QueueObj->Id();
+}
+
+if ($sDay > $Statistics::monthsMaxDay{$sMonth}) {
+ $sDay = $Statistics::monthsMaxDay{$sMonth};
+}
+
+if ($eDay > $Statistics::monthsMaxDay{$eMonth}) {
+ $eDay = $Statistics::monthsMaxDay{$eMonth};
+}
+
+if ($sYear){
+ $sEpoch = timelocal(0, 0, 0, $sDay, $sMonth, $sYear-1900);
+}
+if ($eYear){
+Statistics::DebugLog("eMonth = " . $eMonth . "\n");
+ $eEpoch = timelocal(0, 0, 0, $eDay, $eMonth, $eYear-1900);
+} else {
+ # This case happens when the page is first loaded
+ my @local = localtime(time);
+ ($eDay, $eMonth, $eYear) = ($local[3], $local[4], $local[5]);
+ $eYear += 1900;
+ $eEpoch = timelocal(0, 0, 0, $local[3], $local[4], $local[5], $local[6], $local[7], $local[8]);
+Statistics::DebugLog("Setting eEpoch=$eEpoch from current time.\n");
+}
+
+if (($eEpoch < $sEpoch) || ($sEpoch == 0)) {
+ # We have an end, but not a start, or, overlapping.
+
+ # if $currentMonth is set, just set the day to 1
+ if($currentMonth) {
+ # set start vars from end, but with day set to 1
+ (undef, undef, undef, $sDay, $sMonth, $sYear) = localtime($eEpoch);
+ $sDay=1;
+ $sEpoch = timelocal(0, 0, 0, $sDay, $sMonth, $sYear);
+ } else {
+ # If the user has specified how many days back to go, use that,
+ # If not, set start to configured default period before end
+ if(defined $days) {
+ $sEpoch = $eEpoch - ($days * $Statistics::secsPerDay);
+ } else {
+ $sEpoch = $eEpoch - ($Statistics::PerDayPeriod * $Statistics::secsPerDay);
+ }
+ (undef, undef, undef, $sDay, $sMonth, $sYear) = localtime($sEpoch);
+ }
+ $sYear += 1900;
+}
+
+# Compute days to chart.
+# The +1 is because we need to generate one more date. If the user
+# selected a 10 day range, we need to generate 11 days.
+$diff = int(($eEpoch - $sEpoch + $Statistics::secsPerDay - 1) / $Statistics::secsPerDay)+1;
+Statistics::DebugLog("Setting diff=$diff\n");
+
+Statistics::DebugLog("sEpoch=$sEpoch, components=" . join(',', localtime($sEpoch)) . "\n");
+Statistics::DebugLog("eEpoch=$eEpoch, components=" . join(',', localtime($eEpoch)) . "\n");
+
+# Set up the string for the current query for bookmarkable link
+$QueryString = "sDay=$sDay&sMonth=$sMonth&sYear=$sYear&eDay=$eDay&eMonth=$eMonth&eYear=$eYear&weekends=$weekends&Queue=$Queue";
+
+# Set up the end date to be midnight(morning) of the date after the one the user wanted.
+my $endRange = $eEpoch + $Statistics::secsPerDay;
+my $QueueObj = new RT::Queue($session{'CurrentUser'});
+$QueueObj->Load($Queue);
+$n = 0;
+until ($#dates == $diff) {
+ my $date = new RT::Date($session{CurrentUser});
+ $date->Set(Value=>$endRange - $n, Format => 'unix');
+ # Note: we used to adjust the time to local midnight, but
+ # none of the other date entry fields in RT seem to adjust, so we've stopped.
+ #Statistics::DebugLog("Before adjust to midnight date " . Statistics::FormatDate("%c", $date) . "\n");
+ $n+= $Statistics::secsPerDay;
+ # If we aren't showing weekends and this is one, decrement the number
+ # of days to show and skip to the next date.
+ if(!$weekends and Statistics::RTDateIsWeekend($date)) {$diff--; next;}
+ unshift @dates, $date;
+Statistics::DebugLog("pushing date " . Statistics::FormatDate("%c", $date) . "\n");
+ unshift @{ $data[0] }, Statistics::FormatDate($Statistics::PerDayLabelDateFormat, $date);
+}
+
+# We put an extra day into the lists to cover up till midnight of the next day,
+# But we don't want that to appear in the labels, so pop it off.
+pop( @{ $data[0] } );
+
+</%INIT>
diff --git a/rt/html/RTx/Statistics/DayOfWeek/Elements/Chart b/rt/html/RTx/Statistics/DayOfWeek/Elements/Chart
new file mode 100755
index 000000000..239c09541
--- /dev/null
+++ b/rt/html/RTx/Statistics/DayOfWeek/Elements/Chart
@@ -0,0 +1,26 @@
+% $r->content_type("image/$format");
+% $m->print($graph->plot(\@data)->$format());
+% $m->abort();
+<&|/l, $#data+1&>[_1] Elements</&>:<p>
+% for (0..$#data) {
+<% $data[$_] %><p>
+% }
+<%INIT>
+use GD::Graph::bars;
+
+my @data;
+my $graph = GD::Graph::bars->new($Statistics::GraphWidth,$Statistics::GraphHeight);
+$graph->set(export_format => "png",
+ x_label => 'Day of Week',
+ y_label => 'Ticket actions per Day by type');
+$graph->set_legend(split /,/ , $ARGS{set_legend});
+push @data, [split /,/ , $ARGS{x_labels}];
+push @data, [split /,/ , $ARGS{data1}];
+push @data, [split /,/ , $ARGS{data2}];
+push @data, [split /,/ , $ARGS{data3}];
+
+my $format = $graph->export_format;
+$r->content_type("image/$format");
+</%INIT>
+<%ARGS>
+</%ARGS>
diff --git a/rt/html/RTx/Statistics/DayOfWeek/index.html b/rt/html/RTx/Statistics/DayOfWeek/index.html
new file mode 100755
index 000000000..2e82b9c24
--- /dev/null
+++ b/rt/html/RTx/Statistics/DayOfWeek/index.html
@@ -0,0 +1,155 @@
+<& /Elements/Header, Title =>loc('Tickets by Day Of Week in Queue:' . $QueueObj->Name()) &>
+<& /RTx/Statistics/Elements/Tabs, Title =>loc('Trends in ticket status by Day Of Week in Queue:' . $QueueObj->Name()) &>
+
+<h3>Description</h3>
+<p>The purpose of this page is to show historical trends for each day of the week.
+It displays details of number of tickets created in your
+selected queue for each day. It also hows how many of those created tickets were Resolved or Deleted</p>
+
+<form method="POST" action="index.html">
+
+
+%my $title = "Ticket counts by day of week in " . $QueueObj->Name();
+<&|/Elements/TitleBox,
+ title => $title,
+ title_href => "/RTx/Statistics/DayOfWeek/index.html?$QueryString" &>
+<TABLE BORDER=0 cellspacing=0 cellpadding=1 WIDTH=100%>
+% if ($ShowHeader) {
+<& /RTx/Statistics/Elements/CollectionAsTable/Header,
+ Format => \@Format,
+ FormatString => $Format,
+ AllowSorting => $AllowSorting,
+ Order => $Order,
+ Query => undef,
+ Rows => $Rows,
+ Page => $Page,
+ OrderBy => $OrderBy ,
+ BaseURL => $BaseURL,
+ maxitems => $maxitems &>
+% }
+% my $line = 1;
+% for my $d (0..$#days) {
+% my $x = 1;
+% $values{Statistics_Date} = $days[$d];
+%# NOTE Show all status values???
+% $values{Statistics_Created_Count} = $counts[$d]{new};
+% $values{Statistics_Resolved_Count} = $counts[$d]{resolved};
+% $values{Statistics_Deleted_Count} = $counts[$d]{deleted};
+<& /RTx/Statistics/Elements/CollectionAsTable/Row, Format => \@Format, i => $line, record => $record, maxitems => $maxitems &>
+% $line++;
+% }
+% $values {Statistics_Date} = "Totals";
+% $values {Statistics_Created_Count} = $Totals{new};
+% $values {Statistics_Resolved_Count} = $Totals{resolved};
+% $values {Statistics_Deleted_Count} = $Totals{deleted};
+<& /RTx/Statistics/Elements/CollectionAsTable/Row, Format => \@BoldFormat, i => $line, record => $record, maxitems => $maxitems &>
+</table>
+</&>
+
+<hr>
+
+<BR />
+<BR />
+
+<%perl>
+my $url = 'Elements/Chart?&x_labels=';
+for (0..$#days) {
+ $url .= $days[$_] . "," ;
+}
+chop $url;
+$url .= "&";
+
+my @things = qw(new resolved deleted);
+for my $th (0..$#things) {
+ $url .= "data".(1+$th)."=".(join ",", map { $counts[$_]{$things[$th]} } (0..6))."&";
+}
+chop $url;
+$url .= '&set_legend=Created,Resolved,Deleted';
+</%perl>
+
+<& /RTx/Statistics/Elements/GraphBox, GraphURL => $url &>
+
+% Statistics::DebugLog("queue name=" . $QueueObj->Id() . "\n");
+
+<& /RTx/Statistics/Elements/ControlsAsTable/ControlBox,
+ Title => "Change Queue",
+ ShowSingleQueue => 1, Queue => $QueueObj->Id()
+ &>
+
+</form>
+
+% Statistics::DebugInit( $m );
+
+<%ARGS>
+$Queue => $Statistics::DayOfWeekQueue
+
+$AllowSorting => undef
+$Order => undef
+$OrderBy => undef
+$ShowNavigation => 1
+$ShowHeader => 1
+$Rows => 50
+$Page => 1
+$BaseURL => undef
+</%ARGS>
+
+<%INIT>
+use GD::Graph;
+use RTx::Statistics;
+my @days = qw(Sun Mon Tue Wed Thu Fri Sat);
+my $n = 0;
+my @data = ([]);
+my @msgs;
+my @counts;
+my %Totals = (
+ resolved => 0,
+ deleted => 0,
+ new => 0
+);
+my $QueryString = "Queue=$Queue";
+my $maxitems = 4;
+my %record;
+my %values;
+my $record = \%record;
+
+$record{values} = \%values;
+
+my $Format = qq{ Statistics_Date,
+ '__Statistics_Created_Count__/STYLE:text-align:right;',
+ '__Statistics_Resolved_Count__/STYLE:text-align:right;',
+ '__Statistics_Deleted_Count__/STYLE:text-align:right;' };
+my $BoldFormat = qq{ '<B>__Statistics_Date__</B>',
+ '<B>__Statistics_Created_Count__</B>/STYLE:text-align:right;',
+ '<B>__Statistics_Resolved_Count__</B>/STYLE:text-align:right;',
+ '<B>__Statistics_Deleted_Count__</B>/STYLE:text-align:right;' };
+my (@Format) = $m->comp('/RTx/Statistics/Elements/CollectionAsTable/ParseFormat', Format => $Format);
+my (@BoldFormat) = $m->comp('/RTx/Statistics/Elements/CollectionAsTable/ParseFormat', Format => $BoldFormat);
+
+my $QueueObj = new RT::Queue($session{'CurrentUser'});
+$QueueObj->Load($Queue);
+$RT::Logger->warning("Loaded queue $Queue, name=". $QueueObj->Name());
+
+my $tix = new RT::Tickets($session{'CurrentUser'});
+$tix->LimitQueue (VALUE => $Queue);
+$tix->UnLimit;
+if ($tix->Count) {
+ # Initialize the counters to zero, so that all the cells show up
+ foreach my $day (0..@days) {
+ $counts[$day]{resolved} = 0;
+ $counts[$day]{deleted} = 0;
+ $counts[$day]{new} = 0;
+ }
+ while (my $t = $tix->RT::SearchBuilder::Next) { # BLOODY HACK
+ if($t->Status eq "resolved") {
+ $counts[(localtime($t->ResolvedObj->Unix))[6]]{resolved}++;
+ $Totals{resolved}++;
+ }
+ if($t->Status eq "deleted") {
+ $counts[(localtime($t->LastUpdatedObj->Unix))[6]]{deleted}++;
+ $Totals{deleted}++;
+ }
+ $counts[(localtime($t->CreatedObj->Unix))[6]]{new}++;
+ $Totals{new}++;
+ }
+}
+</%INIT>
diff --git a/rt/html/RTx/Statistics/DurationAsString b/rt/html/RTx/Statistics/DurationAsString
new file mode 100755
index 000000000..c0b4d9af4
--- /dev/null
+++ b/rt/html/RTx/Statistics/DurationAsString
@@ -0,0 +1,18 @@
+<%$days|'00'%> days <%$hours|'00'%>:<%$minutes|'00'%>
+<%INIT>
+
+my $MINUTE = 60;
+my $HOUR = $MINUTE*60;
+my $DAY = $HOUR * 24;
+my $WEEK = $DAY * 7;
+my $days = int($Duration / $DAY);
+$Duration = $Duration % $DAY;
+my $hours = int($Duration / $HOUR);
+$hours = sprintf("%02d", $hours);
+$Duration = $Duration % $HOUR;
+my $minutes = int($Duration/$MINUTE);
+$minutes = sprintf("%02d", $minutes);
+</%INIT>
+<%ARGS>
+$Duration => undef
+</%ARGS>
diff --git a/rt/html/RTx/Statistics/Elements/CollectionAsTable/Header b/rt/html/RTx/Statistics/Elements/CollectionAsTable/Header
new file mode 100644
index 000000000..cecb02eee
--- /dev/null
+++ b/rt/html/RTx/Statistics/Elements/CollectionAsTable/Header
@@ -0,0 +1,126 @@
+%# BEGIN BPS TAGGED BLOCK {{{
+%#
+%# COPYRIGHT:
+%#
+%# This software is Copyright (c) 1996-2005 Best Practical Solutions, LLC
+%# <jesse@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., 675 Mass Ave, Cambridge, MA 02139, USA.
+%#
+%#
+%# 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 }}}
+<%ARGS>
+@Format => undef
+$FormatString => undef
+$AllowSorting => undef
+$Order=>undef
+$BaseURL => undef
+$Query => undef
+$Rows => undef
+$Page => undef
+$maxitems => undef
+</%ARGS>
+<TR class="collection-as-table">
+<%perl>
+
+my %generic_query_args = ( Query => $Query, Rows => $Rows, Page => $Page, Format => $FormatString );
+
+my $item = 0;
+foreach my $col (@Format) {
+ $item++;
+ if ( $col->{title} eq 'NEWLINE' ) {
+ while ( $item < $maxitems ) {
+ $m->out(qq{<th class="collection-as-table">&nbsp;</th>\n});
+ $item++;
+ }
+
+ $item = 0;
+ $m->out(qq{</TR>\n<TR class="collection-as-table">});
+ }
+ else {
+ $m->out('<TH class="collection-as-table" ');
+ $m->out( 'align="' . $col->{align} . '"' ) if ( $col->{align} );
+ $m->out( 'style="' . $col->{style} . '"' ) if ( $col->{style} );
+ $m->out('>');
+ my $title = $col->{title};
+ $title =~ s/^__(.*)__$/$1/o;
+ $title = (
+ $m->comp(
+ '/RTx/Statistics/Elements/StatColumnMap',
+ Name => $title,
+ Attr => 'title'
+ )
+ || $title
+ );
+ if (
+ $AllowSorting
+ && $col->{'attribute'}
+ && $m->comp(
+ '/RTx/Statistics/Elements/StatColumnMap',
+ Name => $col->{'attribute'},
+ Attr => 'attribute'
+ )
+ )
+ {
+
+ $m->out(
+ '<a href="' . $BaseURL
+ . $m->comp(
+ '/Elements/QueryString',
+ %generic_query_args,
+ OrderBy => (
+ $m->comp(
+ '/RTx/Statistics/Elements/StatColumnMap',
+ Name => $col->{'attribute'},
+ Attr => 'attribute'
+ )
+ || $col->{'attribute'}
+ ),
+ Order => ( $ARGS{'Order'} eq 'ASC' ? 'DESC' : 'ASC' )
+ )
+ . '">'
+ . loc($title) . '</a>'
+ );
+ }
+ else {
+ $m->out( loc($title) );
+ }
+ $m->out('</TH>');
+ }
+}
+</%perl>
+</TR>
diff --git a/rt/html/Admin/Global/CustomField.html b/rt/html/RTx/Statistics/Elements/CollectionAsTable/ParseFormat
index 3871d8998..a482f817e 100644
--- a/rt/html/Admin/Global/CustomField.html
+++ b/rt/html/RTx/Statistics/Elements/CollectionAsTable/ParseFormat
@@ -1,8 +1,8 @@
-%# {{{ BEGIN BPS TAGGED BLOCK
+%# BEGIN BPS TAGGED BLOCK {{{
%#
%# COPYRIGHT:
%#
-%# This software is Copyright (c) 1996-2004 Best Practical Solutions, LLC
+%# This software is Copyright (c) 1996-2005 Best Practical Solutions, LLC
%# <jesse@bestpractical.com>
%#
%# (Except where explicitly superseded by other copyright notices)
@@ -42,45 +42,68 @@
%# works based on those contributions, and sublicense and distribute
%# those contributions and any derivatives thereof.
%#
-%# }}} END BPS TAGGED BLOCK
-<& /Admin/Elements/Header, Title => $title &>
-<& /Admin/Elements/SystemTabs,
- current_tab => 'Admin/Global/CustomFields.html',
- current_subtab => $current_subtab,
- subtabs => $subtabs,
- Title => $title &>
+%# END BPS TAGGED BLOCK }}}
+<%ARGS>
+$Format
+</%ARGS>
-<& /Admin/Elements/EditCustomField, title => $title, %ARGS &>
+<%init>
+use Regexp::Common;
+my @Columns;
-<%INIT>
-my ($title, $current_subtab);
+while ($Format =~ /($RE{delimited}{-delim=>qq{\'"}}|[{}\w.]+)/go) {
+ my $col = $1;
-my $subtabs = {
- A => { title => loc('Select custom field'),
- path => "Admin/Global/CustomFields.html"
- },
- B => { title => loc('New custom field'),
- path => "Admin/Global/CustomField.html?create=1&Queue=0",
- separator => 1,
- }
- };
-if ( $ARGS{'create'} ) {
- $current_subtab = "Admin/Global/CustomField.html?create=1&Queue=0";
- $title = loc('Create a CustomField which applies to all queues');
-}
-else {
- $current_subtab =
- "Admin/Global/CustomField.html?CustomField=" . $CustomField . "&Queue=0";
- $title = loc('Modify a CustomField which applies to all queues');
- $subtabs->{"C"} = {
- title => loc( 'Custom Field #[_1]', $CustomField ),
- path => "Admin/Global/CustomField.html?CustomField=" . $CustomField . "&Queue=0"
- };
+ if ($col =~ /^$RE{quoted}$/o) {
+ substr($col,0,1) = "";
+ substr($col,-1,1) = "";
+ }
+
+ my $colref;
+
+ # kfh at mqsoftware.com added this to be able
+ # to create columns where the actual heading and value
+ # aren't know ahead of time. For instance queue names.
+ # it will work with subcols, but all subcols will have the same KEY
+ if ( $col =~ s!/KEY:([^/]+)!!io ) {
+ $colref->{'keyname'} = $1;
+ }
+ if ( $col =~ s!/STYLE:([^/]+)!!io ) {
+ $colref->{'style'} = $1;
+ }
+ if ( $col =~ s!/CLASS:([^/]+)!!io ) {
+ $colref->{'class'} = $1;
+ }
+ if ( $col =~ s!/TITLE:([^/]+)!!io ) {
+ $colref->{'title'} = $1;
+ }
+ if ( $col =~ s!/ALIGN:([^\/]+)!!io ) {
+ $colref->{'align'} = $1;
+ }
+ if ( $col =~ /__(.*?)__/gio ) {
+ my @subcols;
+ while ( $col =~ s/^(.*?)__(.*?)__//o ) {
+ push ( @subcols, $1 ) if ($1);
+ push ( @subcols, "__$2__" );
+ $colref->{'attribute'} = $2;
+ }
+ push ( @subcols, $col );
+ @{ $colref->{'output'} } = @subcols;
+ }
+ else {
+ @{ $colref->{'output'} } = ( "__" . $col . "__" );
+ $colref->{'attribute'} = $col;
+ }
+
+ if ( !$colref->{'title'} && grep { /^__(.*?)__$/io }
+ @{ $colref->{'output'} } )
+ {
+ $colref->{'title'} = $1;
+ $colref->{'attribute'} = $1;
+ }
+
+
+ push @Columns, $colref;
}
-</%INIT>
-<%ARGS>
-$CustomField => undef
-</%ARGS>
-<%ATTR>
-AutoFlush => 0
-</%ATTR>
+ return(@Columns);
+</%init>
diff --git a/rt/html/RTx/Statistics/Elements/CollectionAsTable/Row b/rt/html/RTx/Statistics/Elements/CollectionAsTable/Row
new file mode 100644
index 000000000..bcfabe5c3
--- /dev/null
+++ b/rt/html/RTx/Statistics/Elements/CollectionAsTable/Row
@@ -0,0 +1,112 @@
+%# BEGIN BPS TAGGED BLOCK {{{
+%#
+%# COPYRIGHT:
+%#
+%# This software is Copyright (c) 1996-2005 Best Practical Solutions, LLC
+%# <jesse@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., 675 Mass Ave, Cambridge, MA 02139, USA.
+%#
+%#
+%# 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 }}}
+<%ARGS>
+$i => undef
+@Format => undef
+$record => undef
+$maxitems => undef
+$Depth => undef
+$Warning => undef
+</%ARGS>
+
+<%PERL>
+$m->out('<TR class="' . ( $Warning ? 'warnline' : $i % 2 ? 'oddline' : 'evenline' ) . '" >' );
+my $item;
+foreach my $column (@Format) {
+ if ( $column->{title} eq 'NEWLINE' ) {
+ while ( $item < $maxitems ) {
+ $m->out(qq{<td class="collection-as-table">&nbsp;</td>\n});
+ $item++;
+ }
+ $item = 0;
+ $m->out('</TR>');
+ $m->out('<TR class="'
+ . ( $Warning ? 'warnline' : $i % 2 ? 'oddline' : 'evenline' )
+ . '" >' );
+ next;
+ }
+ $item++;
+ $m->out('<td class="collection-as-table" ');
+ $m->out( 'align="' . $column->{align} . '"' ) if ( $column->{align} );
+ $m->out( 'style="' . $column->{style} . '"' ) if ( $column->{style} );
+ $m->out('>');
+ foreach my $subcol ( @{ $column->{output} } ) {
+ if ( $subcol =~ /^__(.*?)__$/o ) {
+ my $col = $1;
+ my $value = $m->comp(
+ '/RTx/Statistics/Elements/StatColumnMap',
+ Name => $col,
+ Attr => 'value'
+ );
+ my @out;
+
+ if ( $value && ref($value) ) {
+
+ # All HTML snippets are returned by the callback function
+ # as scalar references. Data fetched from the objects are
+ # plain scalars, and needs to be escaped properly.
+ @out =
+ map {
+ ref($_) ? $$_ : $m->interp->apply_escapes( $_ => 'h' )
+ } &{$value}( $record, $i, $column->{keyname} );
+ ;
+ }
+ else {
+
+ # Simple value; just escape it.
+ @out = $m->interp->apply_escapes( $value => 'h' );
+ }
+ s/\n/<br>/gs for @out;
+ $m->out( @out );
+ }
+ else {
+ $m->out($subcol);
+ }
+ }
+ $m->out('</td>');
+}
+$m->out('</TR>');
+</%PERL>
diff --git a/rt/html/RTx/Statistics/Elements/ControlsAsTable/ControlBox b/rt/html/RTx/Statistics/Elements/ControlsAsTable/ControlBox
new file mode 100644
index 000000000..ce043e294
--- /dev/null
+++ b/rt/html/RTx/Statistics/Elements/ControlsAsTable/ControlBox
@@ -0,0 +1,103 @@
+<table class="box" bgcolor="#336699" style="border-style:none solid solid solid;border-width:1px;border-color:#2E2E8C;" cellpadding="0" cellspacing="0">
+ <tbody>
+ <tr>
+ <th style="color: rgb(51, 102, 153);" class="titlebox">
+ <span class="titleboxclose">
+ <a href="#" onclick="hideshow('stats_control')">X</a></span>&nbsp;
+ <span class="titleboxtitle" style="color: rgb(255, 255, 255);">
+ <b><% $Title %></b></span>
+ </th>
+ <th style="color: rgb(51, 102, 153);" class="titleboxright">
+ <span class="titleboxright">&nbsp;</span>
+ </th>
+ </tr>
+ <tr id="element-stats_control">
+ <td colspan="3" class="" bgcolor="#dddddd">
+ <table border="0" cellpadding="1" cellspacing="0">
+% if (defined $ShowStatus) {
+ <tr>
+ <td class="collection-as-table" style="text-align:left;">Show Status:</td>
+ <td COLSPAN=3 class="collection-as-table" style="text-align:left;">
+ <& /Elements/SelectStatus, Name=>"status", Default => $Status, DefaultValue => undef &>
+ </td>
+ </tr>
+% }
+% if (defined $ShowSingleQueue) {
+ <tr>
+ <td class="collection-as-table" style="text-align:left;">Show Queue:</td>
+ <td COLSPAN=3 class="collection-as-table" style="text-align:left;">
+ <& /Elements/SelectQueue, Name=>"Queue", Default=>$Queue ,ShowNullOption=>0,
+ CheckQueueRight=>'SeeQueue' &>
+ </td>
+ </tr>
+% }
+% if (defined $ShowDates) {
+ <tr>
+ <& /RTx/Statistics/Elements/DateSelectRow, Label => "Start Date:",
+ refMonth => $sMonth, nameMonth => "sMonth",
+ refDay => $sDay, nameDay => "sDay",
+ refYear => $sYear, nameYear => "sYear" &>
+ </tr>
+ <tr>
+ <& /RTx/Statistics/Elements/DateSelectRow, Label => "End Date:",
+ refMonth => $eMonth, nameMonth => "eMonth",
+ refDay => $eDay, nameDay => "eDay",
+ refYear => $eYear, nameYear => "eYear" &>
+ </tr>
+ <tr>
+ <td class="collection-as-table" style="text-align:left;">Show Weekends:</td>
+ <td class="collection-as-table" style="text-align:left;">
+ <select name=weekends>
+ <option value=0 <% (!$weekends) && 'selected' %> >No</option>
+ <option value=1 <% $weekends && 'selected' %> >Yes</option>
+ </select>
+ </td>
+ </tr>
+% }
+% if (defined $ShowMultiQueues) {
+ <tr>
+% if (defined $ShowDates) {
+%# If we're showing the dates, we put these side by side.
+ <td COLSPAN=2 class="collection-as-table" style="text-align:left;">Select All Queues: <input type=checkbox name="AddAllCheck"></td>
+ <td COLSPAN=3 class="collection-as-table" >
+ <& /RTx/Statistics/Elements/SelectMultiQueue, Name=>"queues", Selected=>$queues_ref,
+ ShowNullOption=>0, CheckQueueRight=>'SeeQueue', Size => 10, NamedValues => 1 &>
+ </td>
+% } else {
+ <td COLSPAN=3 class="collection-as-table" style="text-align:left;">
+ <& /RTx/Statistics/Elements/SelectMultiQueue, Name=>"queues", Selected=>$queues_ref,
+ ShowNullOption=>0, CheckQueueRight=>'SeeQueue', Size => 10, NamedValues => 1 &>
+ </td>
+ </tr>
+ <tr>
+ <td class="collection-as-table" style="text-align:left;">Select All Queues: <input type=checkbox name="AddAllCheck"></td>
+% }
+ </tr>
+% }
+ <& /RTx/Statistics/Elements/ControlsAsTable/UpdatePage &>
+ </table>
+ </td>
+ </tr>
+ </tbody>
+</table>
+
+
+<BR>
+<%args>
+$Title => undef
+$ShowMultiQueues => undef
+$queues_ref => undef
+$ShowDates => undef
+$sMonth => undef
+$sDay => undef
+$sYear => undef
+$eMonth => undef
+$eDay => undef
+$eYear => undef
+$weekends => undef
+$ShowSingleQueue => undef
+$Queue => undef
+$ShowStatus => undef
+$Status => undef
+</%args>
+
diff --git a/rt/html/RTx/Statistics/Elements/ControlsAsTable/UpdatePage b/rt/html/RTx/Statistics/Elements/ControlsAsTable/UpdatePage
new file mode 100644
index 000000000..b4ccfd56f
--- /dev/null
+++ b/rt/html/RTx/Statistics/Elements/ControlsAsTable/UpdatePage
@@ -0,0 +1,5 @@
+<tr>
+ <td colspan="4" style="text-align:center;padding-top:3px; background-color:#C8C8C8;">
+ <INPUT TYPE="submit" VALUE="<&|/l&>Update Page</&>">
+ </td>
+</tr>
diff --git a/rt/html/RTx/Statistics/Elements/DateSelectRow b/rt/html/RTx/Statistics/Elements/DateSelectRow
new file mode 100644
index 000000000..325e168c9
--- /dev/null
+++ b/rt/html/RTx/Statistics/Elements/DateSelectRow
@@ -0,0 +1,55 @@
+ <td class="collection-as-table" style="text-align:left;"><% $Label %></td>
+ <td class="collection-as-table" style="text-align:left;">
+ <select name=<% $nameMonth %> >
+% for ($n=0;$n<=$#Statistics::months;$n++){
+% if ($$refMonth eq $n){
+% $selected ="selected";
+% }else {
+% $selected ="";
+% }
+ <option value=<% $n %> <% $selected %> ><% $Statistics::months[$n] %></option>
+%}
+ </select>
+ </td>
+ <td class="collection-as-table" style="text-align:left;">
+ <select name=<% $nameDay %> >
+% for ($n=1;$n<=31;$n++){
+% if ($$refDay == $n ){
+% $selected ="selected";
+% }else {
+% $selected ="";
+% }
+ <option value=<% $n %> <% $selected %> ><% $n %></option>
+% }
+ </select>
+ </td>
+ <td class="collection-as-table" style="text-align:left;">
+ <select name=<% $nameYear %> >
+%
+% for ($n=0;$n <= scalar @Statistics::years-1;$n++){
+% if ($Statistics::years[$n] == $$refYear){
+% $selected ="selected";
+% }else{
+% $selected ="";
+% }
+ <option value=<% $Statistics::years[$n] %> <% $selected %> ><% $Statistics::years[$n] %></option>
+% }
+ </select>
+ </td>
+
+
+<%args>
+$Label => undef
+$refMonth => undef
+$nameMonth => undef
+$refDay => undef
+$nameDay => undef
+$refYear => undef
+$nameYear => undef
+</%args>
+<%init>
+use RTx::Statistics;
+my $n;
+my $selected;
+
+</%init>
diff --git a/rt/html/RTx/Statistics/Elements/DurationAsString b/rt/html/RTx/Statistics/Elements/DurationAsString
new file mode 100755
index 000000000..c0b4d9af4
--- /dev/null
+++ b/rt/html/RTx/Statistics/Elements/DurationAsString
@@ -0,0 +1,18 @@
+<%$days|'00'%> days <%$hours|'00'%>:<%$minutes|'00'%>
+<%INIT>
+
+my $MINUTE = 60;
+my $HOUR = $MINUTE*60;
+my $DAY = $HOUR * 24;
+my $WEEK = $DAY * 7;
+my $days = int($Duration / $DAY);
+$Duration = $Duration % $DAY;
+my $hours = int($Duration / $HOUR);
+$hours = sprintf("%02d", $hours);
+$Duration = $Duration % $HOUR;
+my $minutes = int($Duration/$MINUTE);
+$minutes = sprintf("%02d", $minutes);
+</%INIT>
+<%ARGS>
+$Duration => undef
+</%ARGS>
diff --git a/rt/html/RTx/Statistics/Elements/GraphBox b/rt/html/RTx/Statistics/Elements/GraphBox
new file mode 100644
index 000000000..3dc06973e
--- /dev/null
+++ b/rt/html/RTx/Statistics/Elements/GraphBox
@@ -0,0 +1,27 @@
+<div style="float:left; padding-right:30px;">
+<table class="box" bgcolor="#336699" style="border-style:none solid solid solid;border-width:1px;border-color:#2E2E8C;" cellpadding="0" cellspacing="0">
+ <tbody><tr>
+ <th style="color: rgb(51, 102, 153);" class="titlebox">
+ <span class="titleboxclose">
+ <a href="#" onclick="hideshow('stats_chart')">X</a></span>&nbsp;
+
+ <span class="titleboxtitle">
+ <b><a href="<% $GraphURL %>">Download Chart as Image</a></b>
+ </span>
+ </th>
+ <th style="color: rgb(51, 102, 153);" class="titleboxright">
+ <span class="titleboxright">&nbsp;</span>
+ </th>
+ </tr>
+
+ <tr id="element-stats_chart">
+ <td colspan="3" class="" bgcolor="#dddddd">
+ <img src="<% $GraphURL %>" ALT="Result Graph" >
+ </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<%args>
+$GraphURL => undef
+</%args>
diff --git a/rt/html/Admin/Global/CustomFields.html b/rt/html/RTx/Statistics/Elements/SelectMultiQueue
index 593040218..637f6dc80 100644..100755
--- a/rt/html/Admin/Global/CustomFields.html
+++ b/rt/html/RTx/Statistics/Elements/SelectMultiQueue
@@ -1,8 +1,8 @@
-%# {{{ BEGIN BPS TAGGED BLOCK
+%# BEGIN BPS TAGGED BLOCK {{{
%#
%# COPYRIGHT:
%#
-%# This software is Copyright (c) 1996-2004 Best Practical Solutions, LLC
+%# This software is Copyright (c) 1996-2005 Best Practical Solutions, LLC
%# <jesse@bestpractical.com>
%#
%# (Except where explicitly superseded by other copyright notices)
@@ -42,28 +42,40 @@
%# works based on those contributions, and sublicense and distribute
%# those contributions and any derivatives thereof.
%#
-%# }}} END BPS TAGGED BLOCK
-<& /Admin/Elements/Header, Title => $title &>
-<& /Admin/Elements/SystemTabs,
- current_tab => 'Admin/Global/CustomFields.html',
- current_subtab => 'Admin/Global/CustomFields.html',
- subtabs => $subtabs,
- Title => $title &>
-
-<& /Admin/Elements/EditCustomFields, title => $title, %ARGS &>
+%# END BPS TAGGED BLOCK }}}
+<SELECT NAME ="<%$Name%>" multiple size="<% $Size %>">
+% if ($ShowNullOption) {
+<OPTION VALUE="">-</OPTION>
+% }
+% while (my $queue=$q->Next) {
+% if ($ShowAllQueues || $queue->CurrentUserHasRight($CheckQueueRight)) {
+% my $targ="," . $queue->Name . ",";
+<OPTION VALUE="<%($NamedValues ? $queue->Name : $queue->Id) %>" <%( ($sel_list =~ m/$targ/) ? 'SELECTED' : '')%>><%$queue->Name%>
+% if (($Verbose) and ($queue->Description) ){
+(<%$queue->Description%>)
+% }
+</OPTION>
+% }
+% }
+</SELECT>
+<%ARGS>
+$CheckQueueRight => 'CreateTicket'
+$ShowNullOption => 1
+$ShowAllQueues => 1
+$Name => undef
+$Verbose => undef
+$NamedValues => 0
+$Selected => undef # ref to array containing selected queue names
+$Lite => 0
+$Size => 5
+</%ARGS>
<%INIT>
-my $subtabs = {
- A => { title => loc('Select custom field'),
- path => "Admin/Global/CustomFields.html"
- },
- B => { title => loc('New custom field'),
- path => "Admin/Global/CustomField.html?create=1&Queue=0",
- separator => 1,
- }
- };
-my $title = loc("Modify Custom Fields which apply to all queues");
+
+# put list of queue names into string, starting and ending with commas
+my $sel_list = "," . join(",", @$Selected) . ",";
+
+my $q=new RT::Queues($session{'CurrentUser'});
+$q->UnLimit;
+
</%INIT>
-<%ARGS>
-$id => undef
-</%ARGS>
diff --git a/rt/html/RTx/Statistics/Elements/StatColumnMap b/rt/html/RTx/Statistics/Elements/StatColumnMap
new file mode 100644
index 000000000..aef9e2f3e
--- /dev/null
+++ b/rt/html/RTx/Statistics/Elements/StatColumnMap
@@ -0,0 +1,173 @@
+%# BEGIN BPS TAGGED BLOCK {{{
+%#
+%# COPYRIGHT:
+%#
+%# This software is Copyright (c) 1996-2005 Best Practical Solutions, LLC
+%# <jesse@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., 675 Mass Ave, Cambridge, MA 02139, USA.
+%#
+%#
+%# 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 }}}
+<%ARGS>
+$Name => undef
+$Attr => undef
+</%ARGS>
+
+
+<%ONCE>
+our ( $STAT_COLUMN_MAP );
+
+sub StatColumnMap {
+ my $name = shift;
+ my $attr = shift;
+
+ # First deal with the simple things from the map
+ if ( $STAT_COLUMN_MAP->{$name} ) {
+ return ( $STAT_COLUMN_MAP->{$name}->{$attr} );
+ }
+
+ # now, let's deal with harder things, like Custom Fields
+
+ elsif ( $name =~ /^(?:CF|CustomField)\.\{(.+)\}$/ ) {
+ my $field = $1;
+
+ if ( $attr eq 'attribute' ) {
+ return (undef);
+ }
+ elsif ( $attr eq 'title' ) {
+ return ( $field );
+ }
+ elsif ( $attr eq 'value' ) {
+ # Display custom field contents, separated by newlines.
+ # For Image custom fields we also show a thumbnail here.
+ return sub {
+ my $values = $_[0]->CustomFieldValues($field);
+ return map {
+ (
+ ($_->CustomFieldObj->Type eq 'Image')
+ ? \($m->scomp( '/Elements/ShowCustomFieldImage', Object => $_ ))
+ : $_->Content
+ ),
+ \'<br>',
+ } @{ $values->ItemsArrayRef }
+ };
+ }
+ }
+}
+
+sub LinkCallback {
+ my $method = shift;
+
+ my $mode = $RT::Ticket::LINKTYPEMAP{$method}{Mode};
+ my $type = $RT::Ticket::LINKTYPEMAP{$method}{Type};
+ my $mode_uri = $mode.'URI';
+ my $local_type = 'Local'.$mode;
+
+ return sub {
+ map {
+ \'<A HREF="',
+ $_->$mode_uri->Resolver->HREF,
+ \'">',
+ ( $_->$mode_uri->IsLocal ? $_->$local_type : $_->$mode ),
+ \'</A><BR>',
+ } @{ $_[0]->Links($mode,$type)->ItemsArrayRef }
+ }
+}
+
+$STAT_COLUMN_MAP = {
+ LastUpdated => {
+ attribute => 'LastUpdated',
+ title => 'Last Updated',
+ value => sub { return $_[0]->LastUpdatedObj->AsString }
+ },
+
+ Statistics_Date => {
+ title => 'Date',
+ value => sub { return $_[0]{values}{Statistics_Date} }
+ },
+
+ Statistics_Created_Count => {
+ title => 'Created',
+ value => sub { return $_[0]{values}{Statistics_Created_Count} }
+ },
+
+ Statistics_Resolved_Count => {
+ title => 'Resolved',
+ value => sub { return $_[0]{values}{Statistics_Resolved_Count} }
+ },
+
+ Statistics_Deleted_Count => {
+ title => 'Deleted',
+ value => sub { return $_[0]{values}{Statistics_Deleted_Count} }
+ },
+
+ Statistics_Totals => {
+ title => 'Totals',
+ value => sub { return $_[0]{values}{Statistics_Totals} }
+ },
+
+ Statistics_Status => {
+ title => 'Status',
+ value => sub { return $_[0]{values}{Statistics_Status} }
+ },
+
+ Statistics_Dynamic => {
+ # Depends on having a KEY as second param
+ value => sub {
+ my $record = shift;
+ my $line = shift;
+ my $key = shift;
+ return $$record{values}{$key}
+ }
+ },
+
+ # Everything from LINKTYPEMAP
+ (map {
+ $_ => { value => LinkCallback( $_ ) }
+ } keys %RT::Ticket::LINKTYPEMAP),
+
+ '_CLASS' => {
+ value => sub { return $_[1] % 2 ? 'oddline' : 'evenline' }
+ },
+
+};
+</%ONCE>
+<%init>
+$m->comp( '/Elements/Callback', STAT_COLUMN_MAP => $STAT_COLUMN_MAP, _CallbackName => 'StatColumnMap');
+return StatColumnMap($Name, $Attr);
+</%init>
diff --git a/rt/html/RTx/Statistics/Elements/Tabs b/rt/html/RTx/Statistics/Elements/Tabs
new file mode 100755
index 000000000..4fde113ea
--- /dev/null
+++ b/rt/html/RTx/Statistics/Elements/Tabs
@@ -0,0 +1,72 @@
+%# BEGIN LICENSE BLOCK
+%#
+%# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com>
+%#
+%# (Except where explictly superceded by other copyright notices)
+%#
+%# 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.
+%#
+%# Unless otherwise specified, all modifications, corrections or
+%# extensions to this work which alter its source code become the
+%# property of Best Practical Solutions, LLC when submitted for
+%# inclusion in the work.
+%#
+%#
+%# END LICENSE BLOCK
+<& /Elements/Tabs,
+ tabs => $tabs,
+ current_toptab => 'RTx/Statistics/index.html',
+ current_tab => $current_tab,
+ Title => $Title &>
+
+<%INIT>
+ my $tabs = { A => { title => loc('Tickets per Day'),
+ path => 'RTx/Statistics/CallsQueueDay/index.html',
+ },
+ B => { title => loc('Tickets by status'),
+ path => 'RTx/Statistics/OpenStalled/index.html',
+ },
+ C => { title => loc('Multiple Queues'),
+ path => 'RTx/Statistics/CallsMultiQueue/index.html',
+ },
+ D => { title => loc('Ticket Trends by Day'),
+ path => 'RTx/Statistics/DayOfWeek/index.html',
+ },
+ E => { 'title' => loc('Time to Resolve'),
+ path => 'RTx/Statistics/Resolution/index.html',
+ },
+ F => { 'title' => loc('Resolve Time Graph'),
+ path => 'RTx/Statistics/TimeToResolve/index.html',
+ },
+ Z => { 'title' => loc('FAQ'),
+ path => 'RTx/Statistics/FAQ/index.html',
+ },
+ };
+
+ # Now let callbacks add their extra tabs
+ $m->comp('/Elements/Callback', tabs => $tabs, %ARGS);
+
+ foreach my $tab (sort keys %{$tabs}) {
+ if ($tabs->{$tab}->{'path'} eq $current_tab) {
+ $tabs->{$tab}->{"subtabs"} = $subtabs;
+ $tabs->{$tab}->{"current_subtab"} = $current_subtab;
+ }
+ }
+
+</%INIT>
+
+
+<%ARGS>
+$subtabs => undef
+$current_tab => undef
+$current_subtab => undef
+$Title => undef
+</%ARGS>
diff --git a/rt/html/RTx/Statistics/FAQ/index.html b/rt/html/RTx/Statistics/FAQ/index.html
new file mode 100644
index 000000000..e7839eaad
--- /dev/null
+++ b/rt/html/RTx/Statistics/FAQ/index.html
@@ -0,0 +1,23 @@
+<& /Elements/Header, Title => 'FAQ and known issues' &>
+<& /RTx/Statistics/Elements/Tabs, Title => loc("FAQ and Known Issues") &>
+<hr noshade size="1">
+<p>This page will be used to contain known issues and FAQ`s for the Statistics
+package<br />
+This will also be used to clarify limitations of the package as they stand.</p>
+
+<p><strong>What Version of the Statistics package is this?</strong></p>
+<p>0.1.8</p>
+
+<p><strong>What time zone are the charts set to?</strong></p>
+<p>Because of the new programming method of the date functions, the charts are currently built in GMT(UTC). This may once again be
+customisable in a future release.</p>
+
+<p><strong>What is the default date period and queue?</strong></p>
+<p>The default date period is the previous 10 days, except where the chart is over a fixed 7 day period. The default queue is either
+General, or another queue set in your local configuration.</p>
+
+<p><strong>What are the limitations of the date function?</strong></p>
+<p>It has few, but it will not let you chose less than one day. you cannot select an end date before the start date and it is not
+recommended to select a date in the future or an illegal date, such at 30th February. Code has been put in place to trap these, but it may
+not be fool proof.</p>
+<hr size="1" noshade>
diff --git a/rt/html/RTx/Statistics/OpenStalled/Elements/Chart b/rt/html/RTx/Statistics/OpenStalled/Elements/Chart
new file mode 100755
index 000000000..9505881e8
--- /dev/null
+++ b/rt/html/RTx/Statistics/OpenStalled/Elements/Chart
@@ -0,0 +1,27 @@
+<%perl>
+$r->content_type("image/$format");
+print $graph->plot(\@data)->$format();
+$m->abort();
+print $#data+1 . " Elements:<p>";
+for (0..$#data) {
+print $data[$_];
+print "<p>";
+}
+</%perl>
+<%INIT>
+use GD::Graph::bars;
+
+my @data;
+my $graph = GD::Graph::bars->new($Statistics::GraphWidth,$Statistics::GraphHeight);
+$graph->set(export_format => "png",
+ x_label => 'Queue name',
+ y_label => 'Total per queue by status');
+my $format = $graph->export_format;
+$graph->set_legend(split /,/ , $ARGS{set_legend});
+push @data, [split /,/ , $ARGS{x_labels}];
+push @data, [split /,/ , $ARGS{data1}];
+push @data, [split /,/ , $ARGS{data2}];
+push @data, [split /,/ , $ARGS{data3}];
+</%INIT>
+<%ARGS>
+</%ARGS>
diff --git a/rt/html/RTx/Statistics/OpenStalled/Results.tsv b/rt/html/RTx/Statistics/OpenStalled/Results.tsv
new file mode 100644
index 000000000..2ec1e0c4a
--- /dev/null
+++ b/rt/html/RTx/Statistics/OpenStalled/Results.tsv
@@ -0,0 +1,114 @@
+%# BEGIN BPS TAGGED BLOCK {{{
+%#
+%# COPYRIGHT:
+%#
+%# This software is Copyright (c) 1996-2005 Best Practical Solutions, LLC
+%# <jesse@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., 675 Mass Ave, Cambridge, MA 02139, USA.
+%#
+%#
+%# 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 }}}
+<%ARGS>
+@queues => @Statistics::OpenStalledQueueList
+</%ARGS>
+
+<%INIT>
+use RTx::Statistics;
+use Time::Local;
+
+ my $n = 0;
+ my @data;
+ my @msgs;
+ my %totals;
+ my $QueryString;
+ my $now = new RT::Date($session{CurrentUser});
+ my $tix = new RT::Tickets($session{'CurrentUser'});
+
+ my %queues = map {
+ $_ => 1;
+ } (@queues);
+
+ # set content type
+ $r->content_type('application/vnd.ms-excel');
+
+ $QueryString = "queues=" . join("&queues=", @queues);
+
+ my $queue = new RT::Queues($session{CurrentUser});
+ $queue->UnLimit;
+
+ my $QueueObj = new RT::Queue($session{'CurrentUser'});
+ $QueueObj->Load($queue);
+
+ # Put out some data about the generation of this file
+ $m->out("Tickets by Status by Queue for Queues:\t" . join(',', @queues) . "\tGenerated at:\t" . Statistics::FormatDate("%x %X", $now). "\n\n");
+
+ # basically the same as index.html
+
+ # Output header row
+ $m->out("Status");
+ for ( sort keys %queues) {
+ push @data, $_;
+ my $Queueobj = new RT::Queue($session{'CurrentUser'});
+ $Queueobj->Load($_);
+ next if !$Queueobj->CurrentUserHasRight('SeeQueue');
+ $m->out("\t" . $_);
+ }
+ $m->out("\tTotals\n");
+
+ foreach my $s (qw(new open stalled)) {
+ $m->out("$s");
+ my $total=0;
+ foreach my $q (sort keys %queues) {
+ $tix = new RT::Tickets($session{'CurrentUser'});
+ $tix->LimitQueue(VALUE => "$q");
+ $tix->LimitStatus(VALUE => "$s");
+ $totals{$q} += $tix->Count; # Add up columns for each queue
+ $m->out("\t" . $tix->Count);
+ $total += $tix->Count;
+ }
+ $m->out("\t$total\n");
+ $totals{"Totals"} += $total;
+ }
+ $m->out("Totals");
+ foreach my $q (sort keys %queues) {
+ $m->out("\t" . $totals{$q});
+ }
+ $m->out("\t" . $totals{"Totals"} . "\n");
+
+ $m->abort();
+</%INIT>
diff --git a/rt/html/RTx/Statistics/OpenStalled/index.html b/rt/html/RTx/Statistics/OpenStalled/index.html
new file mode 100755
index 000000000..d0cd9f158
--- /dev/null
+++ b/rt/html/RTx/Statistics/OpenStalled/index.html
@@ -0,0 +1,188 @@
+<& /Elements/Header, Title => loc('New, Open and Stalled tickets by Queue') &>
+<& /RTx/Statistics/Elements/Tabs, Title => loc('New, Open and Stalled tickets by Queue') &>
+
+<h3>Description</h3>
+<p>The purpose of this page is to show a snapshot of the current status of tickets by Queue. You can multi select Queues from the dropdown
+list or simply show all available queues. This will indicate how many tickets have not yet been viewed (New), how many have been at least
+viewed once (Open) and how many have had their status changed to stalled.</p>
+
+<form method="POST" action="index.html">
+
+%my $tix = new RT::Tickets($session{'CurrentUser'});
+%if ($queue) {
+% $tix->LimitQueue (VALUE => $queue);
+%}
+
+
+%my $title = "New, Open and Stalled Tickets in " . join(', ', @queues);
+<& /Elements/TitleBoxStart, title => $title, title_href => "/RTx/Statistics/OpenStalled/index.html?$QueryString"&>
+<TABLE BORDER=0 cellspacing=0 cellpadding=1 WIDTH="100%">
+% if ($ShowHeader) {
+<& /RTx/Statistics/Elements/CollectionAsTable/Header,
+ Format => \@RowFormat,
+ FormatString => $RowFormat,
+ AllowSorting => $AllowSorting,
+ Order => $Order,
+ Query => undef,
+ Rows => $Rows,
+ Page => $Page,
+ OrderBy => $OrderBy ,
+ BaseURL => $BaseURL,
+ maxitems => $maxitems &>
+% }
+
+% for ( sort keys %queues_to_show) {
+% push @data, $_;
+% }
+% my @legend;
+% my $total = 0;
+% my $line = 0;
+%# NOTE need to handle all status values (see share/html/Elements/SelectStatus).
+% foreach my $s (qw(new open stalled)) {
+% $line++;
+% push @legend, $s;
+% $total=0;
+% foreach my $q (sort keys %queues_to_show) {
+% $tix = new RT::Tickets($session{'CurrentUser'});
+% $tix->LimitQueue(VALUE => "$q");
+% $tix->LimitStatus(VALUE => "$s");
+% push @data, $tix->Count;
+% $totals{$q} += $tix->Count; # Add up columns for each queue
+% $total += $tix->Count;
+% $values{$q} = $tix->Count;
+% }
+% $totals{"Totals"} += $total;
+% $values{Statistics_Status} = $s;
+% $values{Statistics_Totals} = $total;
+<& /RTx/Statistics/Elements/CollectionAsTable/Row, Format => \@RowFormat, i => $line, record => $record, maxitems => $maxitems &>
+% }
+% $values{Statistics_Status} = "Totals";
+% foreach my $q (sort keys %queues_to_show) {
+% $values{$q} = $totals{$q};
+% }
+% $values{Statistics_Totals} = $totals{"Totals"};
+<& /RTx/Statistics/Elements/CollectionAsTable/Row, Format => \@BoldRowFormat, i => $line+1, record => $record, maxitems => $maxitems &>
+</table>
+<& /Elements/TitleBoxEnd&>
+
+<hr>
+
+<BR />
+<BR />
+
+% use Data::Dumper;
+% Statistics::DebugLog("Dump of data array is " . Dumper(@data) . "\n");
+% my $url = 'Elements/Chart?x_labels=';
+% for (1..(scalar keys %queues_to_show)) {
+% $url .= $m->interp->apply_escapes((shift @data),'u') . ',';
+% }
+% chop $url;
+% $url .= '&data1=' ;
+% for (1..(scalar keys %queues_to_show)) {
+% $url .= $m->interp->apply_escapes((shift @data),'u') . ',';
+% }
+% chop $url;
+% $url .= '&data2=' ;
+% for (1..(scalar keys %queues_to_show)) {
+% $url .= $m->interp->apply_escapes((shift @data),'u') . ',';
+% }
+% chop $url;
+% $url .= '&data3=' ;
+% for (1..(scalar keys %queues_to_show)) {
+% $url .= $m->interp->apply_escapes((shift @data),'u') . ',';
+% }
+% $url .= '&set_legend='.(join ",", @legend);
+
+
+<& /RTx/Statistics/Elements/GraphBox, GraphURL => $url &>
+
+<& /RTx/Statistics/Elements/ControlsAsTable/ControlBox, Title => "Select Queues", ShowMultiQueues => 1, queues_ref => \@queues &>
+
+<a href="<%$RT::WebPath%>/RTx/Statistics/OpenStalled/index.html?<% $QueryString %>"><&|/l&>Bookmarkable link</&></a>
+%# | <a href="<%$RT::WebPath%>/RTx/Statistics/OpenStalled/Results.tsv?<%$QueryString%>"><&|/l&>spreadsheet</&></a>
+<BR>
+<BR>
+
+</FORM>
+
+% Statistics::DebugInit( $m );
+
+<%ARGS>
+@queues => @Statistics::OpenStalledQueueList
+$AllowSorting => undef
+$Order => undef
+$OrderBy => undef
+$ShowNavigation => 1
+$ShowHeader => 1
+$Rows => 50
+$Page => 1
+$BaseURL => undef
+$AddAllCheck => undef
+</%ARGS>
+
+<%INIT>
+ use RTx::Statistics;
+
+ my $n = 0;
+ my @data;
+ my @msgs;
+ my %totals;
+ my $QueryString;
+ my %queues_to_show;
+ my $maxitems;
+ my $RowFormat;
+ my $BoldRowFormat;
+ my %record;
+ my %values;
+ my $record = \%record;
+
+ $record{values} = \%values;
+
+ Statistics::DebugClear();
+
+ # Handle the Add All Checkbox
+ if($AddAllCheck eq "on") {
+ $AddAllCheck = undef;
+ undef (@queues);
+ my $q=new RT::Queues($session{'CurrentUser'});
+ $q->UnLimit;
+ while (my $queue=$q->Next) {
+ next if !$queue->CurrentUserHasRight('SeeQueue');
+ push @queues, $queue->Name;
+ }
+ }
+
+ # If the user has the right to see the queue, put it into the map
+ for my $q (@queues) {
+ my $Queueobj = new RT::Queue($session{'CurrentUser'});
+ $Queueobj->Load($q);
+ next if !$Queueobj->CurrentUserHasRight('SeeQueue');
+ $queues_to_show{$q} = 1;
+ }
+
+ $maxitems = (scalar @queues) + 2;
+
+ # Build the new query string
+ $QueryString = "queues=" . join("&queues=", @queues);
+
+ # Build the format strings
+ $RowFormat = "'__Statistics_Status__'";
+ $BoldRowFormat = "'<B>__Statistics_Status__</B>'";
+ for my $q (@queues) {
+ $RowFormat .= ",'__Statistics_Dynamic__/KEY:$q/TITLE:$q/STYLE:text-align:right;'";
+ $BoldRowFormat .= ",'<B>__Statistics_Dynamic__</B>/KEY:$q/TITLE:$q/STYLE:text-align:right;'";
+ }
+ $RowFormat .= ",'<B>__Statistics_Totals__</B>/STYLE:text-align:right;'";
+ $BoldRowFormat .= ",'<B>__Statistics_Totals__</B>/STYLE:text-align:right;'";
+ # Parse the formats into structures.
+ my (@RowFormat) = $m->comp('/RTx/Statistics/Elements/CollectionAsTable/ParseFormat', Format => $RowFormat);
+ my (@BoldRowFormat) = $m->comp('/RTx/Statistics/Elements/CollectionAsTable/ParseFormat', Format => $BoldRowFormat);
+
+
+ my $queue = new RT::Queues($session{CurrentUser});
+ $queue->UnLimit;
+
+ my $QueueObj = new RT::Queue($session{'CurrentUser'});
+ $QueueObj->Load($queue);
+
+</%INIT>
diff --git a/rt/html/RTx/Statistics/Resolution/Elements/Chart b/rt/html/RTx/Statistics/Resolution/Elements/Chart
new file mode 100755
index 000000000..fa0ac5538
--- /dev/null
+++ b/rt/html/RTx/Statistics/Resolution/Elements/Chart
@@ -0,0 +1,29 @@
+<%perl>
+$r->content_type("image/$format");
+print $graph->plot(\@data)->$format();
+$m->abort();
+print $#data+1 . " Elements:<p>";
+for (0..$#data) {
+print $data[$_];
+print "<p>";
+}
+</%perl>
+<%INIT>
+use GD::Graph::lines;
+
+my @data;
+my $graph = GD::Graph::lines->new($Statistics::GraphWidth,$Statistics::GraphHeight);
+$graph->set(export_format => "png",
+ x_label => 'Days',
+ y_label => 'Average time in Days');
+
+push @data, [split /,/ , $ARGS{x_labels}];
+push @data, [split /,/ , $ARGS{data1}];
+push @data, [split /,/ , $ARGS{data2}];
+push @data, [split /,/ , $ARGS{data3}];
+
+my $format = $graph->export_format;
+#$r->content_type("image/$format");
+</%INIT>
+<%ARGS>
+</%ARGS>
diff --git a/rt/html/RTx/Statistics/Resolution/index.html b/rt/html/RTx/Statistics/Resolution/index.html
new file mode 100644
index 000000000..d9885b093
--- /dev/null
+++ b/rt/html/RTx/Statistics/Resolution/index.html
@@ -0,0 +1,269 @@
+<& /Elements/Header, Title => 'Time to Resolution' &>
+<& /RTx/Statistics/Elements/Tabs, Title => loc("Time To Resolve tickets by Queue for : " .$QueueObj->Name()) &>
+<h3>Description</h3>
+<p>This page shows details of resolution of tickets in the selected queue. It displays tickets created on each day in your selected date
+range. Of those tickets created on that day, how many have been resolved and the total time it has taken for all tickets created on that
+day to be resolved.</p>
+<p>At the bottom of the chart is shows total time taken to resolve all tickets
+in the selected date range and the average time per ticket to
+resolve.</p>
+
+<form method="POST" action="index.html">
+
+%my $title = "Time to resolve in " . $QueueObj->Name() . " per day from " .
+% Statistics::FormatDate($Statistics::PerDayDateFormat, $dates[0]) . " through " .
+% Statistics::FormatDate($Statistics::PerDayDateFormat, $dates[$#dates-1]);
+<&|/Elements/TitleBox,
+ title => $title,
+ title_href => "/RTx/Statistics/Resolution/index.html?$QueryString" &>
+<TABLE BORDER=0 cellspacing=0 cellpadding=1 WIDTH=100%>
+% if ($ShowHeader) {
+<& /RTx/Statistics/Elements/CollectionAsTable/Header,
+ Format => \@Format,
+ FormatString => $Format,
+ AllowSorting => $AllowSorting,
+ Order => $Order,
+ Query => undef,
+ Rows => $Rows,
+ Page => $Page,
+ OrderBy => $OrderBy ,
+ BaseURL => $BaseURL,
+ maxitems => $maxitems &>
+% }
+% my $line = 1;
+% LINE: for my $d (0..$#dates ) {
+% if ($d == $#dates ){
+% next LINE;
+% }
+% my $x = 1;
+% $values{Statistics_Date} = Statistics::FormatDate($Statistics::PerDayDateFormat, $dates[$d]);
+% my $tix = new RT::Tickets($session{'CurrentUser'});
+% $tix->LimitCreated(VALUE => $dates[$d]->ISO, OPERATOR => ">=");
+% if ($dates[$d+1]) {
+% $tix->LimitCreated(VALUE => $dates[$d+1]->ISO, OPERATOR => "<=");
+% }
+% if ($Queue) {
+% $tix->LimitQueue (VALUE => $Queue);
+% }
+% $values{Statistics_Created_Count} = $tix->Count;
+% $tix->LimitStatus(VALUE => "resolved");
+% $values{Statistics_Resolved_Count} = $tix->Count;
+% if ($tix->Count) {
+% my @tix = @{$tix->ItemsArrayRef};
+% my $total;
+% $total += ($_->ResolvedObj->Unix - $_->CreatedObj->Unix) for @tix;
+% $size+= ($#tix +1);
+% $grandtotal += $total;
+% $values{Duration} = Statistics::DurationAsString($total);
+% $data[$x++][$d] = int ($total );
+% } else {
+% $values{Duration} = "N/A";
+% }
+<& /RTx/Statistics/Elements/CollectionAsTable/Row, Format => \@Format, i => $line, record => $record, maxitems => $maxitems &>
+% $line++;
+%}
+% $size =1 if $size==0;
+% $values{text} = "Average time to resolve = " . Statistics::DurationAsString($grandtotal / $size);
+<& /RTx/Statistics/Elements/CollectionAsTable/Row, Format => \@OneCellFormat, i => $line, record => $record, maxitems => $maxitems &>
+% $line++;
+% $values{text} = "Total time to resolve = " . Statistics::DurationAsString( $grandtotal );
+<& /RTx/Statistics/Elements/CollectionAsTable/Row, Format => \@OneCellFormat, i => $line, record => $record, maxitems => $maxitems &>
+% $line++;
+</table>
+</&>
+
+<hr>
+
+<BR />
+<BR />
+
+<%perl>
+# Create the graph URL
+
+# change the total time to resolve to a floating point number of days
+foreach my $dat(@{$data[1]} ){
+ $dat = ($dat / $Statistics::secsPerDay);
+ $dat = sprintf("%0.4f", $dat);
+}
+
+my $url = 'Elements/Chart?x_labels=';
+for (0..$diff-1) {
+ $url .= $data[0][$_] . ",";
+}
+chop $url;
+shift @data;
+$url .= "&data1=";
+for(0..$diff-1) {
+ $data[0][$_] = 0 if !$data[0][$_];
+ $url .= $data[0][$_] . ",";
+}
+</%perl>
+
+<& /RTx/Statistics/Elements/GraphBox, GraphURL => $url &>
+
+<& /RTx/Statistics/Elements/ControlsAsTable/ControlBox,
+ Title => "Change Queue or Dates",
+ ShowDates => 1, sMonth => \$sMonth, sDay => \$sDay, sYear => \$sYear,
+ eMonth => \$eMonth, eDay => \$eDay, eYear => \$eYear,
+ weekends => $weekends,
+ ShowSingleQueue => 1, Queue => $Queue
+ &>
+
+</form>
+
+<%ARGS>
+$max => $Statistics::TimeToResolveMaxRows
+$Queue => undef
+$weekends =>$Statistics::TimeToResolveWeekends
+$sMonth=>undef
+$sDay=>undef
+$sYear=>undef
+$eMonth=>undef
+$eDay=>undef
+$eYear=>undef
+$days=>undef
+$currentMonth=>undef
+
+$AllowSorting => undef
+$Order => undef
+$OrderBy => undef
+$ShowNavigation => 1
+$ShowHeader => 1
+$Rows => 50
+$Page => 1
+$BaseURL => undef
+</%ARGS>
+
+<%INIT>
+use RTx::Statistics;
+use Time::Local;
+my $n = 0;
+my @data = ([]);
+my @dates;
+my @msgs;
+my $size;
+my $selected;
+my $grandtotal = 0;
+my $diff;
+my $sEpoch=0;
+my $eEpoch=0;
+my $QueryString;
+
+my $maxitems = 4;
+my %record;
+my %values;
+my $record = \%record;
+
+$record{values} = \%values;
+
+
+# If debugging, set things up and display all the args
+Statistics::DebugClear();
+Statistics::DebugLog("CallsQueueDay/index.html ARGS:\n");
+for my $key (keys %ARGS) {
+ Statistics::DebugLog("ARG{ $key }=" . $ARGS{$key} . "\n");
+}
+
+my $Format = qq{ Statistics_Date,
+ '__Statistics_Created_Count__/STYLE:text-align:right;',
+ '__Statistics_Resolved_Count__/STYLE:text-align:right;',
+ '__Statistics_Dynamic__/KEY:Duration/TITLE:Time To Resolve/STYLE:text-align:right;' };
+my $BoldFormat = qq{ '<B>__Statistics_Date__</B>',
+ '<B>__Statistics_Created_Count__</B>/STYLE:text-align:right;',
+ '<B>__Statistics_Resolved_Count__</B>/STYLE:text-align:right;',
+ '<B>__Statistics_Dynamic__</B>/KEY:Duration/TITLE:Time To Resolve/STYLE:text-align:right;' };
+
+# TODO need way to make this cell do colspan
+my $OneCellFormat = qq{ '<B>__Statistics_Dynamic__</B>/KEY:text/STYLE:text-align:left;','','','' };
+
+my (@Format) = $m->comp('/RTx/Statistics/Elements/CollectionAsTable/ParseFormat', Format => $Format);
+my (@BoldFormat) = $m->comp('/RTx/Statistics/Elements/CollectionAsTable/ParseFormat', Format => $BoldFormat);
+my (@OneCellFormat) = $m->comp('/RTx/Statistics/Elements/CollectionAsTable/ParseFormat', Format => $OneCellFormat);
+
+Statistics::DebugLog("CallsQueueDay/index.html Format array=" . join(',', @Format) . "\n");
+
+if ($sDay > $Statistics::monthsMaxDay{$sMonth}) {
+ $sDay = $Statistics::monthsMaxDay{$sMonth};
+}
+
+if ($eDay > $Statistics::monthsMaxDay{$eMonth}) {
+ $eDay = $Statistics::monthsMaxDay{$eMonth};
+}
+
+if ($sYear){
+ $sEpoch = timelocal(0, 0, 0, $sDay, $sMonth, $sYear-1900);
+}
+if ($eYear){
+Statistics::DebugLog("eMonth = " . $eMonth . "\n");
+ $eEpoch = timelocal(0, 0, 0, $eDay, $eMonth, $eYear-1900);
+} else {
+ # This case happens when the page is first loaded
+ my @local = localtime(time);
+ ($eDay, $eMonth, $eYear) = ($local[3], $local[4], $local[5]);
+ $eYear += 1900;
+ $eEpoch = timelocal(0, 0, 0, $local[3], $local[4], $local[5], $local[6], $local[7], $local[8]);
+Statistics::DebugLog("Setting eEpoch=$eEpoch from current time.\n");
+}
+
+if (($eEpoch < $sEpoch) || ($sEpoch == 0)) {
+ # We have an end, but not a start, or, overlapping.
+
+ # if $currentMonth is set, just set the day to 1
+ if($currentMonth) {
+ # set start vars from end, but with day set to 1
+ (undef, undef, undef, $sDay, $sMonth, $sYear) = localtime($eEpoch);
+ $sDay=1;
+ $sEpoch = timelocal(0, 0, 0, $sDay, $sMonth, $sYear);
+ } else {
+ # If the user has specified how many days back to go, use that,
+ # If not, set start to configured default period before end
+ if(defined $days) {
+ $sEpoch = $eEpoch - ($days * $Statistics::secsPerDay);
+ } else {
+ $sEpoch = $eEpoch - ($Statistics::PerDayPeriod * $Statistics::secsPerDay);
+ }
+ (undef, undef, undef, $sDay, $sMonth, $sYear) = localtime($sEpoch);
+ }
+ $sYear += 1900;
+}
+
+# Compute days to chart.
+# The +1 is because we need to generate one more date. If the user
+# selected a 10 day range, we need to generate 11 days.
+$diff = int(($eEpoch - $sEpoch + $Statistics::secsPerDay - 1) / $Statistics::secsPerDay)+1;
+Statistics::DebugLog("Setting diff=$diff\n");
+
+Statistics::DebugLog("sEpoch=$sEpoch, components=" . join(',', localtime($sEpoch)) . "\n");
+Statistics::DebugLog("eEpoch=$eEpoch, components=" . join(',', localtime($eEpoch)) . "\n");
+
+my $QueueObj = new RT::Queue($session{'CurrentUser'});
+if (!defined $Queue) {
+ $QueueObj->Load($Statistics::TimeToResolveQueue);
+ $Queue = $QueueObj->Id();
+}
+
+# Set up the string for the current query for bookmarkable link
+$QueryString = "sDay=$sDay&sMonth=$sMonth&sYear=$sYear&eDay=$eDay&eMonth=$eMonth&eYear=$eYear&weekends=$weekends&Queue=$Queue";
+
+# Set up the end date to be midnight(morning) of the date after the one the user wanted.
+my $endRange = $eEpoch + $Statistics::secsPerDay;
+$QueueObj->Load($Queue);
+# NOTE: list loop starts at the end of the date range, unshifting dates onto
+# the arrays, so that they end up in start to finish order.
+$eEpoch += $Statistics::secsPerDay;
+$n = 0;
+until ($#dates == $diff ) {
+ my $date = new RT::Date($session{CurrentUser});
+ $date->Set(Value=>$endRange - $n, Format => 'unix');
+ # Note: we used to adjust the time to local midnight, but
+ # none of the other date entry fields in RT seem to adjust, so we've stopped.
+ #Statistics::DebugLog("Before adjust to midnight date " . Statistics::FormatDate("%c", $date) . "\n");
+ $n+= $Statistics::secsPerDay;
+ # If we aren't showing weekends and this is one, decrement the number
+ # of days to show and skip to the next date.
+ if(!$weekends and Statistics::RTDateIsWeekend($date)) {$diff--; next;}
+ unshift @dates, $date;
+Statistics::DebugLog("pushing date " . Statistics::FormatDate("%c", $date) . "\n");
+ unshift @{ $data[0] }, Statistics::FormatDate($Statistics::PerDayLabelDateFormat, $date);
+}
+</%INIT>
diff --git a/rt/html/RTx/Statistics/TimeToResolve/Elements/Chart b/rt/html/RTx/Statistics/TimeToResolve/Elements/Chart
new file mode 100755
index 000000000..a069a7bfb
--- /dev/null
+++ b/rt/html/RTx/Statistics/TimeToResolve/Elements/Chart
@@ -0,0 +1,23 @@
+<%perl>
+print $graph->plot(\@data)->$format();
+$m->abort();
+</%perl>
+<%INIT>
+use GD::Graph::points;
+
+my @data;
+my $graph = GD::Graph::points->new(400,300);
+$graph->set(export_format => "png",
+ marker_size => $ARGS{marker_size},
+ x_label => 'Average time to resolve (Days)',
+ y_label => 'Number of tickets resolved' );
+#$r->content_type("image/$format");
+my $format = $graph->export_format;
+push @data, [split /,/ , $ARGS{x_labels}];
+for (1..((scalar keys %ARGS)-2)) {
+ push @data, [split /,/ , $ARGS{"data".$_}];
+}
+
+</%INIT>
+<%ARGS>
+</%ARGS>
diff --git a/rt/html/RTx/Statistics/TimeToResolve/index.html b/rt/html/RTx/Statistics/TimeToResolve/index.html
new file mode 100755
index 000000000..2124b538d
--- /dev/null
+++ b/rt/html/RTx/Statistics/TimeToResolve/index.html
@@ -0,0 +1,75 @@
+<& /Elements/Header, Title => 'Time to Resolve in Queue' &>
+<& /RTx/Statistics/Elements/Tabs, Title => 'Time to Resolve, by ticket in Queue:' . $QueueObj->Name() &>
+
+<h3>Description</h3>
+<p>This page displays the same information as the Time to Resolve chart, but in a scattergraph format and only for the previous 7 calendar
+days. It only displays data for tickets which have been resolved. Each division on the Days axis is one day and the granularity of this chart
+is 30 minutes.</p>
+<form method="POST">
+
+<table>
+ <tr>
+ <td>Show Queue:</td>
+ <td COLSPAN=3><& /Elements/SelectQueue, Name=>"queue", Default=>$queue ,ShowNullOption=>0,
+ CheckQueueRight=>'SeeQueue' &></td>
+ </tr>
+</table>
+<INPUT TYPE="submit" VALUE="Update Page"</INPUT>
+</form>
+
+<BR>
+% my $url = 'Elements/Chart?x_labels=';
+% my $i;
+% $url .= join ",", (map {(int($_/2) == $_/2 && (++$i)%2) ? $_/2 : ""} grep {$counts[$_]} 0..($#counts-1)), "longer";
+% $url .= '&';
+% $url .= "marker_size=1&";
+% $url .= "data1=".(join ",", map { $_ || () } @counts)."&";
+% chop $url;
+<IMG SRC="<% $url %>">
+
+<BR>
+
+%Statistics::DebugInit($m);
+
+<%ARGS>
+$queue => undef
+</%ARGS>
+
+<%INIT>
+use RTx::Statistics;
+
+my @days = qw(Sun Mon Tue Wed Thu Fri Sat);
+my $n = 0;
+my @data = ([]);
+my @msgs;
+my @counts;
+
+Statistics::DebugClear();
+Statistics::DebugLog("TimeToResolve/index.html ARGS:\n");
+for my $key (keys %ARGS) {
+ Statistics::DebugLog("ARG{ $key }=" . $ARGS{$key} . "\n");
+}
+
+my $QueueObj = new RT::Queue($session{'CurrentUser'});
+if (!defined $queue) {
+ $QueueObj->Load($Statistics::TimeToResolveGraphQueue);
+ $queue = $QueueObj->Id();
+} else {
+ $QueueObj->Load($queue);
+}
+
+
+my $tix = new RT::Tickets($session{'CurrentUser'});
+$tix->LimitQueue (VALUE => $queue) if $queue;
+$tix->LimitStatus(VALUE => "resolved");
+$tix->UnLimit;
+if ($tix->Count) {
+ while (my $t = $tix->RT::SearchBuilder::Next) { # BLOODY HACK
+ my $when = $t->ResolvedObj->Unix - $t->CreatedObj->Unix;
+ next unless $when > 0; # Doubly bloody hack
+ my $max = (60*60*24*2) / 1800;
+ my $x = int($when / 1800);
+ $counts[$x > $max ? $max : $x]++;
+ }
+}
+</%INIT>
diff --git a/rt/html/RTx/Statistics/UserTest/Elements/Chart b/rt/html/RTx/Statistics/UserTest/Elements/Chart
new file mode 100755
index 000000000..99eb2a2b1
--- /dev/null
+++ b/rt/html/RTx/Statistics/UserTest/Elements/Chart
@@ -0,0 +1,28 @@
+<%perl>
+print $graph->plot(\@data)->$format();
+$m->abort();
+print $#data+1 . " Elements:<p>";
+for (0..$#data) {
+print $data[$_];
+print "<p>";
+}
+</%perl>
+<%INIT>
+use GD::Graph::lines;
+
+my @data;
+my $graph = GD::Graph::lines->new(640,480);
+$graph->set(export_format => "png",
+ x_label => 'Days',
+ y_label => 'Average time in Days');
+
+push @data, [split /,/ , $ARGS{x_labels}];
+push @data, [split /,/ , $ARGS{data1}];
+push @data, [split /,/ , $ARGS{data2}];
+push @data, [split /,/ , $ARGS{data3}];
+
+my $format = $graph->export_format;
+#$r->content_type("image/$format");
+</%INIT>
+<%ARGS>
+</%ARGS>
diff --git a/rt/html/RTx/Statistics/UserTest/index.html b/rt/html/RTx/Statistics/UserTest/index.html
new file mode 100755
index 000000000..7bc25da70
--- /dev/null
+++ b/rt/html/RTx/Statistics/UserTest/index.html
@@ -0,0 +1,54 @@
+<& /Elements/Header, Title => 'Time to Resolve in Queue' &>
+<& /RTx/Statistics/Elements/Tabs, Title => 'Time to Resolve, by ticket in Queue:' . $QueueObj->Name() &>
+
+
+<form method="POST">
+
+See Queue:<BR>
+<& /Elements/SelectQueue, Name=>"queue", Default => "$queue" &>
+<BR>
+<INPUT TYPE="submit" VALUE="Go!"</INPUT>
+</form>
+
+<BR>
+% my $url = 'Elements/Chart?x_labels=';
+% my $i;
+% $url .= join ",", (map {(int($_/2) == $_/2 && (++$i)%2) ? $_/2 : ""} grep {$counts[$_]} 0..($#counts-1)), "longer";
+% $url .= '&';
+% $url .= "marker_size=1&";
+% $url .= "data1=".(join ",", map { $_ || () } @counts)."&";
+% chop $url;
+<IMG SRC="<% $url %>">
+
+<BR>
+
+<%ARGS>
+$queue => $Statistics::TimeToResolveGraphQueue;
+</%ARGS>
+
+<%INIT>
+use RTx::Statistics;
+
+my @days = qw(Sun Mon Tue Wed Thu Fri Sat);
+my $n = 0;
+my @data = ([]);
+my @msgs;
+my @counts;
+
+my $QueueObj = new RT::Queue($session{'CurrentUser'});
+$QueueObj->Load($queue);
+
+my $tix = new RT::Tickets($session{'CurrentUser'});
+$tix->LimitQueue (VALUE => $queue) if $queue;
+$tix->LimitStatus(VALUE => "resolved");
+$tix->UnLimit;
+if ($tix->Count) {
+ while (my $t = $tix->RT::SearchBuilder::Next) { # BLOODY HACK
+ my $when = $t->ResolvedObj->Unix - $t->CreatedObj->Unix;
+ next unless $when > 0; # Doubly bloody hack
+ my $max = (60*60*24*2) / 1800;
+ my $x = int($when / 1800);
+ $counts[$x > $max ? $max : $x]++;
+ }
+}
+</%INIT>
diff --git a/rt/html/RTx/Statistics/index.html b/rt/html/RTx/Statistics/index.html
new file mode 100755
index 000000000..41490de18
--- /dev/null
+++ b/rt/html/RTx/Statistics/index.html
@@ -0,0 +1,59 @@
+%# BEGIN LICENSE BLOCK
+%#
+%# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com>
+%#
+%# (Except where explictly superceded by other copyright notices)
+%#
+%# Copyright this file (c) 2003 Harald Wagener <hwagener@hamburg.fcb.com>
+%#
+%# 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.
+%#
+%# Unless otherwise specified, all modifications, corrections or
+%# extensions to this work which alter its source code become the
+%# property of Best Practical Solutions, LLC when submitted for
+%# inclusion in the work.
+%#
+%#
+%# END LICENSE BLOCK
+<& /Elements/Header, Title => loc('RT Statistics') &>
+<& /RTx/Statistics/Elements/Tabs, Title => loc('RT Statistics') &>
+
+<&|/l&><h2>Description</h2>
+<p>These 6 options below enable you to display management data from the RT Database in table and graphical forms, enabling trends, bottlenecks, load problems etc to be identified.
+Each contains a description of how the data is displayed and describes the options available to you.</p></&>
+<ul>
+<li><strong><a href="CallsQueueDay/index.html">
+<&|/l&>Tickets per day per Queue</&></a></strong><br />
+<&|/l&>View the number of tickets created, resolved or deleted in a<br /> specific Queue, over the requested period of days</&>
+</li>
+<li><strong><a href="OpenStalled/index.html">
+<&|/l&>Tickets status by Queue</&></a></strong><br>
+<&|/l&>View numbers of new, open and stalled tickets in a selected Queue</&>
+</li>
+<li><strong><a href="CallsMultiQueue/index.html">
+<&|/l&>Tickets per Day in Multiple Queues</&>
+</a></strong><br>
+<&|/l&>View tickets created, resolved or deleted on in one or more Queues<br /> over a specified time period</&>
+</li>
+<li><strong><a href="DayOfWeek/index.html">
+<&|/l&>Tickets per Day of Week (absolute)</&></a></strong><br>
+<&|/l&>View trends showing when tickets are created, resolved or deleted</&>
+</li>
+<li><strong><a href="Resolution/index.html">
+<&|/l&>Time to Resolve</&></a></strong><br>
+<&|/l&>View how long tickets take to be resolved by Queue</&>
+</li>
+</li>
+<li><strong><a href="TimeToResolve/index.html">
+<&|/l&>Time to Resolve (scatter graph)</&></a></strong><br>
+<&|/l&>View a detailed scatter graph of time to resolve tickets by Queue</&>
+</li>
+</ul>
diff --git a/rt/html/Reports/Activity/ActivityDetail.html b/rt/html/Reports/Activity/ActivityDetail.html
new file mode 100644
index 000000000..ef0d830f7
--- /dev/null
+++ b/rt/html/Reports/Activity/ActivityDetail.html
@@ -0,0 +1,83 @@
+<&|Elements/Wrapper, %ARGS, title => loc("Activity detail"),
+ path => "Reports/Activity/ActivityDetail.html",
+ &>
+
+<& Elements/MiniPlot, data => \%counts &>
+
+<table style="width: 100%">
+<tr class="titlerow">
+<th>Queue</th><th>Activity</th><th>Date</th><th>Time</th><th>Ticket #</th><th>User</th><th>Short description</th>
+</tr>
+% for my $item (@items) {
+<tr>
+<td><% $item->{queue} %></td>
+<td><% $item->{status} %></td>
+<td><% $item->{date} %></td>
+<td><% $item->{time} %></td>
+<td><% $item->{id} %></td>
+<td><% $item->{actor} %></td>
+<td><% $item->{notes} %></td>
+</tr>
+% }
+</table>
+
+</&>
+<%args>
+$query => 'id > 0'
+$start => "2005/01/01"
+$end => "2006/01/01"
+</%args>
+<%init>
+
+
+my $summary_tickets = RT::Tickets->new($session{'CurrentUser'});
+$summary_tickets->FromSQL($query . " AND ( Updated >= '$start' AND Updated <= '$end')");
+my %counts;
+while (my $ticket = $summary_tickets->Next) {
+ my $txns = $ticket->Transactions;
+ $txns->Limit(FIELD => 'Created', OPERATOR => '>=', VALUE => $start);
+ $txns->Limit(FIELD => 'Created', OPERATOR => '<=', VALUE => $end);
+ # I think they really don't just want status changes
+ $txns->Limit(FIELD => 'Type', VALUE => 'Status', ENTRYAGGREGATOR => 'OR');
+ $txns->Limit(FIELD => 'Type', VALUE => 'Create');
+
+ while (my $txn = $txns->Next){
+ my $date = substr($txn->Created, 0, 10);
+ # we don't have data on the status of a new ticket, default to 'new'
+ $counts{$date}{$txn->NewValue || 'new'}++;
+ }
+}
+
+
+my $tickets = RT::Tickets->new($session{'CurrentUser'});
+$tickets->FromSQL($query);
+my @items;
+while (my $ticket = $tickets->Next) {
+ my $txns = $ticket->Transactions;
+ $txns->Limit(FIELD => 'Created', OPERATOR => '>=', VALUE => $start);
+ $txns->Limit(FIELD => 'Created', OPERATOR => '<=', VALUE => $end);
+ # I think they really don't just want status changes
+ $txns->Limit(FIELD => 'Type', VALUE => 'Status', ENTRYAGGREGATOR => 'OR');
+ $txns->Limit(FIELD => 'Type', VALUE => 'Create');
+
+ while (my $txn = $txns->Next) {
+ push @items, { queue => $txn->TicketObj->QueueObj->Name,
+ id => $txn->TicketObj->id,
+ date => (split ' ', $txn->CreatedObj->ISO)[0],
+ time => (split ' ', $txn->CreatedObj->ISO)[1],
+ status => $txn->NewValue || 'new',
+ actor => $txn->CreatorObj->Name,
+ notes => ($txn->Content ne 'This transaction appears to have no content' ? substr($txn->Content, 0, 60) : $txn->BriefDescription)
+ };
+ }
+}
+
+@items = sort {
+ $a->{queue} cmp $b->{'queue'}
+ || $a->{'status'} cmp $b->{'status'}
+ || $a->{'id'} <=> $b->{'id'}
+ || $a->{'actor'} cmp $b->{'actor'}
+ || $a->{'notes'} <=> $b->{'notes'}
+} @items;
+
+</%init>
diff --git a/rt/html/Reports/Activity/ActivitySummary.html b/rt/html/Reports/Activity/ActivitySummary.html
new file mode 100644
index 000000000..7bb756fbc
--- /dev/null
+++ b/rt/html/Reports/Activity/ActivitySummary.html
@@ -0,0 +1,61 @@
+<&|Elements/Wrapper, %ARGS, title => loc("Activity summary"),
+ path => "Reports/Activity/ActivitySummary.html",
+ &>
+
+<& Elements/MiniPlot, data => \%queues &>
+
+<table style="width: 100%">
+<tr class="titlerow">
+<th>Queue</th>
+% for my $status (sort keys %status) {
+<th><% $status %></th>
+% }
+<th>Total</th>
+</tr>
+% for my $queue (sort keys %queues) {
+<th class="label"><% $queue %></th>
+% for my $status (sort keys %status) {
+<td><% $queues{$queue}{$status} || 0 %>
+% }
+<td><% $total{$queue} %></td>
+</tr>
+% }
+<tr class="grandtotal">
+<th class="label" >Grand Total</th>
+% for my $status (sort keys %status) {
+<td><% $status{$status} %></td>
+% }
+<td><% $total %></td>
+</table>
+</&>
+<%args>
+$query => 'id > 0'
+$start => "2005/01/01"
+$end => "2006/01/01"
+</%args>
+<%init>
+
+my $tickets = RT::Tickets->new($session{'CurrentUser'});
+$tickets->FromSQL($query . " AND ( Updated >= '$start' AND Updated <= '$end')");
+
+my %queues;
+my %status;
+my %total;
+my $total;
+while (my $ticket = $tickets->Next) {
+ my $txns = $ticket->Transactions;
+ $txns->Limit(FIELD => 'Created', OPERATOR => '>=', VALUE => $start);
+ $txns->Limit(FIELD => 'Created', OPERATOR => '<=', VALUE => $end);
+ $txns->Limit(FIELD => 'Type', VALUE => 'Status', ENTRYAGGREGATOR => 'OR');
+ $txns->Limit(FIELD => 'Type', VALUE => 'Create');
+
+ while (my $txn = $txns->Next) {
+ $queues{$txn->TicketObj->QueueObj->Name}{$txn->NewValue || 'new'}++;
+ $status{$txn->NewValue || 'new'}++;
+ $total{$txn->TicketObj->QueueObj->Name}++;
+ $total++;
+ }
+}
+
+
+</%init>
diff --git a/rt/html/Reports/Activity/Elements/LimitReport b/rt/html/Reports/Activity/Elements/LimitReport
new file mode 100644
index 000000000..7c4aac73b
--- /dev/null
+++ b/rt/html/Reports/Activity/Elements/LimitReport
@@ -0,0 +1,23 @@
+<form action="index.html" method="POST" enctype="multipart/form-data">
+Query:
+<textarea name="query" rows="5" cols="80"><% $query %></textarea><br />
+
+Report type: <select name="type">
+<option value="ActivityDetail" <% $ARGS{path} =~ /ActivityDetail/ ? 'selected' : '' %>>Activity detail</option>
+<option value="ActivitySummary" <% $ARGS{path} =~ /ActivitySummary/ ? 'selected' : '' %>>Activity summary</option>
+<option value="ResolutionComments" <% $ARGS{path} =~ /ResolutionComments/ ? 'selected' : '' %>>Resolution comments</option>
+<option value="ResolutionStatistics" <% $ARGS{path} =~ /ResolutionStatistics/ ? 'selected' : '' %>>Resolution statistics</option>
+</select><br />
+
+Start date: <input type="text" name="start" value="<% $start %>" /><br />
+End date: <input type="text" name="end" value="<% $end %>" /><br />
+<& /Elements/Submit, Label => loc('Report') &>
+</form>
+<%args>
+$type => undef
+$start => undef
+$end => undef
+$query => undef
+</%args>
+<%init>
+</%init>
diff --git a/rt/html/Reports/Activity/Elements/MiniPlot b/rt/html/Reports/Activity/Elements/MiniPlot
new file mode 100644
index 000000000..f92032818
--- /dev/null
+++ b/rt/html/Reports/Activity/Elements/MiniPlot
@@ -0,0 +1,57 @@
+<table class="miniplot"><tr>
+% for my $major (@major) {
+<td><div class="graph">
+ <ul>
+% my $i = 0;
+% for my $minor (@minor) {
+% my $percent = int( 100 * ($data->{$major}{$minor} || 0) / $max );
+ <li class="c<% ($i % 6) + 1%>" style="width: <% $barwidth %>%;
+ left: <% $baroffset + $each * $i %>%;
+ height: <% $percent %>%;"><div class="data"><% $minor %>: <% $percent %>%</div></li>
+% $i++;
+% }
+ </ul>
+</div></td>
+% }
+</tr><tr>
+% for my $major (@major) {
+<th class="legend"><% $major %></th>
+% }
+</tr>
+</table>
+
+<table class="miniplot"><tr>
+% my $i = 0;
+% for my $minor (@minor) {
+<th><span class="demoblock c<% ($i++ % 6) + 1 %>"></span> <% $minor %></th>
+% }
+</tr>
+</table>
+
+<%args>
+$data
+$major => undef
+$minor => undef
+</%args>
+<%init>
+
+my $max = 1;
+
+my %minor;
+for my $major (keys %{$data}) {
+ for (keys %{$data->{$major}}) {
+ $minor{$_}++;
+ $max = $data->{$major}{$_} if $data->{$major}{$_} > $max;
+ }
+}
+
+my @major = $major ? @{$major} : sort keys %{$data};
+my @minor = $minor ? @{$minor} : sort keys %minor;
+
+return unless @minor and @major;
+
+my $each = int( (100 / @minor) );
+my $barwidth = int( (100 / @minor) * (3/4) );
+my $baroffset = int( (100 / @minor) * (1/8) );
+
+</%init>
diff --git a/rt/html/Reports/Activity/Elements/PrintFooter b/rt/html/Reports/Activity/Elements/PrintFooter
new file mode 100644
index 000000000..fa9f47582
--- /dev/null
+++ b/rt/html/Reports/Activity/Elements/PrintFooter
@@ -0,0 +1,7 @@
+<hr/>
+<div style="text-align: center;">
+<%$RT::ReportFooterMessage || 'Proprietary and Confidential' %>
+</div>
+</body>
+</html>
+%$m->abort();
diff --git a/rt/html/Reports/Activity/Elements/PrintHeader b/rt/html/Reports/Activity/Elements/PrintHeader
new file mode 100644
index 000000000..b7c4b3419
--- /dev/null
+++ b/rt/html/Reports/Activity/Elements/PrintHeader
@@ -0,0 +1,32 @@
+<%args>
+$title => undef
+$path => undef
+$query => undef
+</%args>
+<HTML>
+<HEAD>
+<TITLE><%$title%></TITLE>
+<link rel="shortcut icon" href="<%$RT::WebImagesURL%>/favicon.png" type="image/png" />
+<link media="all" rel="stylesheet" href="<%$RT::WebPath%>/NoAuth/webrt.css" type="text/css" />
+<link media="print" rel="stylesheet" href="<%$RT::WebPath%>/NoAuth/printrt.css" type="text/css" />
+%# XXX TODO THIS SHOULD NOT BE A TABLE
+<body>
+<table width="100%">
+<tr>
+<td align="left">
+<div id="username">User: <%$session{'CurrentUser'}->Name%></div>
+<div id="reportdate">
+%my $d= RT::Date->new($session{'CurrentUser'}); $d->SetToNow;
+<%$d->AsString%></div>
+</td>
+<td align="center">
+<h1><%$title%></h1>
+</td>
+<td align="right">
+<img src="<%$RT::LogoURL%>" alt="RT Logo"/>
+</td>
+</tr>
+</table>
+<hr/>
+<&|/l&>Report criteria:</&> <%$query%>
+<hr />
diff --git a/rt/html/Reports/Activity/Elements/ScreenFooter b/rt/html/Reports/Activity/Elements/ScreenFooter
new file mode 100644
index 000000000..235b7b306
--- /dev/null
+++ b/rt/html/Reports/Activity/Elements/ScreenFooter
@@ -0,0 +1,13 @@
+<& LimitReport, %ARGS &>
+% if ($show_print_link) {
+<div align="right">
+% my %printable_args = %ARGS;
+% delete $printable_args{$_} for (qw/path title mode/);
+% $printable_args{'mode'} = 'print';
+% my $url = $ARGS{'path'} .'?'. join(';', map { $_."=".$printable_args{$_} } keys %printable_args);
+<a href="<%$RT::WebPath|n%>/<%$url|n%>"><&|/l&>Printable version</&></a>
+</div>
+% }
+<%args>
+$show_print_link => 1
+</%args>
diff --git a/rt/html/Reports/Activity/Elements/ScreenHeader b/rt/html/Reports/Activity/Elements/ScreenHeader
new file mode 100644
index 000000000..080efc0dd
--- /dev/null
+++ b/rt/html/Reports/Activity/Elements/ScreenHeader
@@ -0,0 +1,8 @@
+<%args>
+$title => undef
+$path => undef
+</%args>
+<& /Elements/Header, Title => $title &>
+<& Tabs,
+ current_subtab => $path,
+ Title => $title &>
diff --git a/rt/html/Reports/Activity/Elements/Tabs b/rt/html/Reports/Activity/Elements/Tabs
new file mode 100644
index 000000000..a9498209e
--- /dev/null
+++ b/rt/html/Reports/Activity/Elements/Tabs
@@ -0,0 +1,52 @@
+<& /Elements/Tabs,
+ tabs => $tabs,
+ subtabs => $subtabs,
+ current_toptab => 'Tools/Offline.html',
+ current_tab => 'Reports/Activity/index.html'.$args,
+ Title => $Title &>
+
+<%INIT>
+my $subtabs = {};
+
+my $top = $m->caller_args(-1);
+my $args = "?" . $m->comp( '/Elements/QueryString',
+ query => $top->{query},
+ start => $top->{start},
+ end => $top->{end});
+if ($m->caller_args(-1)->{'query'}) {
+ $current_subtab .= $args;
+ $subtabs = {
+ a => { title => 'Activity detail',
+ path => 'Reports/Activity/ActivityDetail.html'.$args,
+ },
+ b => { title => 'Activity summary',
+ path => 'Reports/Activity/ActivitySummary.html'.$args,
+ },
+ c => { title => 'Resolution comments',
+ path => 'Reports/Activity/ResolutionComments.html'.$args,
+ },
+ d => { title => 'Resolution statistics',
+ path => 'Reports/Activity/ResolutionStatistics.html'.$args,
+ },
+ };
+}
+
+my $tabs = {
+ a => { title => loc('Offline'),
+ path => 'Tools/Offline.html',
+ },
+ r => { title => loc('Reports'),
+ path => 'Reports/Activity/index.html'.$args,
+ subtabs => $subtabs,
+ current_subtab => $current_subtab,
+ }
+ };
+
+</%INIT>
+
+
+<%ARGS>
+$current_tab => undef
+$current_subtab => undef
+$Title => undef
+</%ARGS>
diff --git a/rt/html/Reports/Activity/Elements/Wrapper b/rt/html/Reports/Activity/Elements/Wrapper
new file mode 100644
index 000000000..6f81f5f50
--- /dev/null
+++ b/rt/html/Reports/Activity/Elements/Wrapper
@@ -0,0 +1,16 @@
+<%args>
+$mode => 'screen'
+</%args>
+
+% if ($mode eq 'print') {
+<& PrintHeader, %ARGS &>
+%} else {
+<& ScreenHeader, %ARGS &>
+% }
+<%$m->content |n%>
+% if ($mode eq 'print') {
+<& PrintFooter, %ARGS &>
+%} else {
+<& ScreenFooter, %ARGS &>
+% }
+
diff --git a/rt/html/Reports/Activity/ResolutionComments.html b/rt/html/Reports/Activity/ResolutionComments.html
new file mode 100644
index 000000000..81ca301cc
--- /dev/null
+++ b/rt/html/Reports/Activity/ResolutionComments.html
@@ -0,0 +1,62 @@
+<&|Elements/Wrapper, %ARGS, title => loc("Resolution Comments"),
+ path => "Reports/Activity/ResolutionComments.html",
+ &>
+
+<table style="width: 100%">
+<tr>
+<th>Queue</th><th>Ticket #</th><th>Created</th><th>Resolved</th><th>Time to resolve</th>
+</tr>
+<tr>
+<th colspan="5">Resolution comments</th>
+</tr>
+% for my $item (@items) {
+<tr class="titlerow">
+<td><% $item->{queue} %></td>
+<td><% $item->{id} %></td>
+<td><% $item->{created} %></td>
+<td><% $item->{resolved} %></td>
+<td><% $item->{duration} %></td>
+</tr>
+<tr>
+<td colspan="5"><% $item->{whiteboard} %></td>
+</tr>
+% }
+</table>
+</&>
+
+<%args>
+$query => 'id > 0'
+$start => "2005/01/01"
+$end => "2006/01/01"
+</%args>
+<%init>
+
+use Time::Duration;
+
+my $summary_tickets = RT::Tickets->new( $session{'CurrentUser'} );
+$summary_tickets->FromSQL(
+ $query . " AND (Status = 'resolved') AND ( Updated >= '$start' AND Updated <= '$end')" );
+
+my @items;
+while ( my $ticket = $summary_tickets->Next ) {
+ push @items, {
+ queue => $ticket->QueueObj->Name,
+ id => $ticket->id,
+ created => $ticket->CreatedObj->AsString,
+ resolved => $ticket->ResolvedObj->AsString,
+ duration => Time::Duration::concise(
+ Time::Duration::duration(
+ $ticket->ResolvedObj->Unix - $ticket->CreatedObj->Unix
+ )
+ ),
+ whiteboard => $ticket->FirstCustomFieldValue('Whiteboard')
+ };
+}
+
+@items = sort { $a->{queue} cmp $b->{queue} || $a->{id} <=> $b->{id} } @items;
+
+
+
+
+
+</%init>
diff --git a/rt/html/Reports/Activity/ResolutionStatistics.html b/rt/html/Reports/Activity/ResolutionStatistics.html
new file mode 100644
index 000000000..4ecde2c82
--- /dev/null
+++ b/rt/html/Reports/Activity/ResolutionStatistics.html
@@ -0,0 +1,95 @@
+<&|Elements/Wrapper, %ARGS, title => loc("Resolution statistics"),
+ path => "Reports/Activity/ResolutionStatistics.html",
+ &>
+
+<& Elements/MiniPlot,
+ data => \%plot,
+ major => ['Date range','Last 30 days','Last 60 days','Last 90 days','Ever'],
+ minor => [(sort keys %queues), "Average"]
+ &>
+
+<table style="width: 100%">
+<tr>
+<td></td><th colspan="4">Number of tickets closed / Average resolution time per ticket</th>
+</tr>
+<tr class="titlerow">
+<th>Queue</th>
+<th>Date range</th>
+<th>Last 30 days</th>
+<th>Last 60 days</th>
+<th>Last 90 days</th>
+<th>Ever</th>
+</tr>
+% for my $queue (sort keys %queues) {
+<tr>
+<th><% $queue %></th>
+% for my $period ('Date range','Last 30 days','Last 60 days','Last 90 days','Ever') {
+<td><% scalar @{$closed{$period}{$queue}} %> / <% $average_resolve_times{$period}{$queue} %></td>
+% }
+</tr>
+% }
+<tr class="grandtotal">
+<th>Ticket average</th>
+% for my $period ('Date range','Last 30 days','Last 60 days','Last 90 days','Ever') {
+<td><% $average_resolve_times{$period}{_all_count} %> / <% $average_resolve_times{$period}{_all} %></td>
+% }
+</tr>
+</table>
+
+</&>
+<%args>
+$query => 'id > 0'
+$start => "2005/01/01"
+$end => "2006/01/01"
+</%args>
+<%init>
+
+my $in_30_days = RT::Date->new($session{'CurrentUser'});
+$in_30_days->Set(Format => 'Unix', Value => ( time - (86400*30)));
+my $in_60_days = RT::Date->new($session{'CurrentUser'});
+$in_60_days->Set(Format => 'Unix', Value => ( time - (86400*60)));
+my $in_90_days = RT::Date->new($session{'CurrentUser'});
+$in_90_days->Set(Format => 'Unix', Value => ( time - (86400*90)));
+
+my %queries;
+$queries{'Date range'} = "(Resolved >= '$start' AND Resolved <= '$end')";
+$queries{'Last 30 days'} = "(Resolved >= '".$in_30_days->ISO."')";
+$queries{'Last 60 days'} = "(Resolved >= '".$in_60_days->ISO."')";
+$queries{'Last 90 days'} = "(Resolved >= '".$in_90_days->ISO."')";
+$queries{'Ever'} = "(Status = 'resolved' OR Status = 'rejected')";
+
+
+my %closed;
+my %queues;
+foreach my $period (keys %queries) {
+ my $tix = RT::Tickets->new($session{'CurrentUser'});
+ $tix->FromSQL($query . " AND " .$queries{$period});
+
+ while (my $ticket = $tix->Next) {
+ push @{ $closed{$period}{$ticket->QueueObj->Name}}, $ticket;
+ $queues{$ticket->QueueObj->Name}++;
+ }
+}
+
+my %restimes;
+my %average_resolve_times;
+my %plot;
+use Time::Duration;
+foreach my $period ( keys %closed ) {
+ foreach my $queue ( keys %{$closed{$period}} ) {
+ foreach my $ticket (@{$closed{$period}{$queue}} ) {
+ push @{$restimes{$period}{$queue}}, ( $ticket->ResolvedObj->Unix - $ticket->CreatedObj->Unix);
+ }
+
+ my $total_time = 0;
+ $total_time+= $_ for @{$restimes{$period}{$queue}};
+ $average_resolve_times{$period}{'_all_time'} += $total_time;
+ $average_resolve_times{$period}{'_all_count'} += @{$restimes{$period}{$queue}};
+ $plot{$period}{$queue} = $total_time / @{$restimes{$period}{$queue}};
+ $average_resolve_times{$period}{$queue} = Time::Duration::concise(Time::Duration::duration($plot{$period}{$queue}));
+ }
+ $plot{$period}{Average} = $average_resolve_times{$period}{'_all_time'} / $average_resolve_times{$period}{'_all_count'};
+ $average_resolve_times{$period}{'_all'} = Time::Duration::concise(Time::Duration::duration($plot{$period}{Average}));
+}
+
+</%init>
diff --git a/rt/html/Reports/Activity/index.html b/rt/html/Reports/Activity/index.html
new file mode 100644
index 000000000..1f6ddb0d5
--- /dev/null
+++ b/rt/html/Reports/Activity/index.html
@@ -0,0 +1,29 @@
+<&| Elements/Wrapper, %ARGS, title => loc("Activity reports"), show_print_link => 0 &>
+
+
+</&>
+
+<%args>
+$type => undef
+$start => undef
+$end => undef
+$query => "Status = 'resolved'"
+</%args>
+<%init>
+
+unless ($start) {
+ my $then = RT::Date->new($session{'CurrentUser'});
+ $then->Set(Format => 'Unix', Value => time - (86400*7));
+ $ARGS{start} = substr($then->ISO,0,10);
+}
+
+unless ($end) {
+ my $now = RT::Date->new($session{'CurrentUser'});
+ $now->SetToNow();
+ $ARGS{end} = substr($now->ISO,0,10);
+}
+
+if ($type) {
+ $m->redirect($type . ".html?" . $m->comp('/Elements/QueryString', query => $query, start => $start, end => $end));
+}
+</%init>
diff --git a/rt/html/Search/Bulk.html b/rt/html/Search/Bulk.html
index 9742df5ae..b7c64e3f8 100644
--- a/rt/html/Search/Bulk.html
+++ b/rt/html/Search/Bulk.html
@@ -2,7 +2,7 @@
%#
%# COPYRIGHT:
%#
-%# This software is Copyright (c) 1996-2007 Best Practical Solutions, LLC
+%# This software is Copyright (c) 1996-2005 Best Practical Solutions, LLC
%# <jesse@bestpractical.com>
%#
%# (Except where explicitly superseded by other copyright notices)
@@ -22,9 +22,7 @@
%#
%# 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/copyleft/gpl.html.
+%# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
%#
%#
%# CONTRIBUTION SUBMISSION POLICY:
@@ -45,220 +43,185 @@
%# those contributions and any derivatives thereof.
%#
%# END BPS TAGGED BLOCK }}}
-<& /Elements/Header, Title => $title &>
-<& /Ticket/Elements/Tabs,
- current_tab => "Search/Bulk.html",
- Title => $title,
- Format => $ARGS{'Format'}, # we don't want the locally modified one
- Query => $Query,
- Rows => $Rows,
- OrderBy => $OrderBy,
- Order => $Order &>
+<& /Elements/Header, Title => loc("Bulk ticket update") &>
+<& /Elements/Tabs, Title => loc("Bulk ticket update") &>
<& /Elements/ListActions, actions => \@results &>
-<form method="post" action="<%$RT::WebPath%>/Search/Bulk.html" enctype="multipart/form-data">
-% foreach my $var qw(Query Format OrderBy Order Rows Page) {
-<input type="hidden" class="hidden" name="<%$var%>" value="<%$ARGS{$var}%>" />
+<FORM METHOD="POST" ACTION="<%$RT::WebPath%>/Search/Bulk.html" >
+<input type="hidden" name="Query" value="<%$ARGS{'Query'}%>">
+<TABLE WIDTH=100% border=0 cellpadding=3 CELLSPACING=0>
+<TR>
+<TH><&|/l&>Update</&></TH>
+%foreach my $col (@cols) {
+% my $colalias = $col;
+% $colalias =~ s/(Obj\-\>|)(Name|AsString)//;
+
+<TH><% loc($colalias) %>&nbsp;</TH>
%}
-<& /Elements/TicketList, Query => $Query,
- DisplayFormat => $Format,
- Format => $ARGS{'Format'},
- Verbatim => 1,
- AllowSorting => 1,
- OrderBy => $OrderBy,
- Order => $Order,
- Rows => $Rows,
- Page => $Page,
- BaseURL => $RT::WebPath."/Search/Bulk.html?"
- &>
-
-<hr>
-
-<& /Elements/Submit, Label => loc('Update'), CheckAll => 1, ClearAll => 1 &>
-<br />
-<&|/Widgets/TitleBox, title => $title &>
-<table>
-<tr>
-<td valign="top">
+</TR>
+
+<%PERL>
+
+my $i;
+
+$Tickets->RedoSearch();
+while (my $Ticket = $Tickets->Next) {
+ $i++;
+ if ($i % 2) {
+ $bgcolor = "#d4d4d4";
+ }
+ else {
+ $bgcolor = "#ffffff";
+ }
+ </%PERL>
+<TR bgcolor="<%$bgcolor%>">
+<TD><input type=checkbox name="UpdateTicket<%$Ticket->Id%>" value="1" CHECKED></TD>
+%foreach my $col (@cols) {
+<TD>
+% if ($col eq 'id') {
+<A HREF="<% $RT::WebPath%>/Ticket/Display.html?id=<%$Ticket->Id%>"><%$Ticket->Id()%></A>
+% }
+%else {
+<% eval "\$Ticket->$col()" %>&nbsp;
+%}
+</TD>
+%}
+</TR>
+%}
+
+
+
+</TABLE>
+
+<HR>
+
+
+<& /Elements/TitleBoxStart, title => loc('Update selected tickets') &>
+<TABLE>
+<TR>
+<TD VALIGN=TOP>
<table>
-<tr><td class="label"> <&|/l&>Make Owner</&>: </td>
-<td class="value"> <& /Elements/SelectOwner, Name => "Owner" &> (<input type="checkbox" class="checkbox" name="ForceOwnerChange" /> <&|/l&>Force change</&>) </td></tr>
-<tr><td class="label"> <&|/l&>Add Requestor</&>: </td>
-<td class="value"> <input name="AddRequestor" size="20" /> </td></tr>
-<tr><td class="label"> <&|/l&>Remove Requestor</&>: </td>
-<td class="value"> <input name="DeleteRequestor" size="20" /> </td></tr>
-<tr><td class="label"> <&|/l&>Add Cc</&>: </td>
-<td class="value"> <input name="AddCc" size="20" /> </td></tr>
-<tr><td class="label"> <&|/l&>Remove Cc</&>: </td>
-<td class="value"> <input name="DeleteCc" size="20" /> </td></tr>
-<tr><td class="label"> <&|/l&>Add AdminCc</&>: </td>
-<td class="value"> <input name="AddAdminCc" size="20" /> </td></tr>
-<tr><td class="label"> <&|/l&>Remove AdminCc</&>: </td>
-<td class="value"> <input name="DeleteAdminCc" size="20" /> </td></tr>
+<tr><td class=label> <&|/l&>Make Owner</&>: </td>
+<td class=value> <& /Elements/SelectOwner, Name => "Owner" &> (<input type=checkbox name="ForceOwnerChange"> <&|/l&>Force change</&>) </td></tr>
+<tr><td class=label> <&|/l&>Add Requestor</&>: </td>
+<td class=value> <INPUT Name="AddRequestor" SIZE=20> </td></tr>
+<tr><td class=label> <&|/l&>Remove Requestor</&>: </td>
+<td class=value> <INPUT Name="DeleteRequestor" SIZE=20> </td></tr>
+<tr><td class=label> <&|/l&>Add Cc</&>: </td>
+<td class=value> <INPUT Name="AddCc" SIZE=20> </td></tr>
+<tr><td class=label> <&|/l&>Remove Cc</&>: </td>
+<td class=value> <INPUT Name="DeleteCc" SIZE=20> </td></tr>
+<tr><td class=label> <&|/l&>Add AdminCc</&>: </td>
+<td class=value> <INPUT Name="AddAdminCc" SIZE=20> </td></tr>
+<tr><td class=label> <&|/l&>Remove AdminCc</&>: </td>
+<td class=value> <INPUT Name="DeleteAdminCc" SIZE=20> </td></tr>
</table>
-</td>
-<td valign="top">
+</TD>
+<TD VALIGN=TOP>
<table>
-<tr><td class="label"> <&|/l&>Make subject</&>: </td>
-<td class="value"> <input name="Subject" size="20" /> </td></tr>
-<tr><td class="label"> <&|/l&>Make priority</&>: </td>
-<td class="value"> <input name="Priority" size="4" /> </td></tr>
-<tr><td class="label"> <&|/l&>Make queue</&>: </td>
-<td class="value"> <& /Elements/SelectQueue, Name => "Queue" &> </td></tr>
-<tr><td class="label"> <&|/l&>Make Status</&>: </td>
-<td class="value"> <& /Elements/SelectStatus, Name => "Status" &> </td></tr>
-<tr><td class="label"> <&|/l&>Make date Starts</&>: </td>
-<td class="value"> <& /Elements/SelectDate, Name => "Starts_Date", ShowTime => 0, Default => '' &> </td></tr>
-<tr><td class="label"> <&|/l&>Make date Started</&>: </td>
-<td class="value"> <& /Elements/SelectDate, Name => "Started_Date", ShowTime => 0, Default => '' &> </td></tr>
-<tr><td class="label"> <&|/l&>Make date Told</&>: </td>
-<td class="value"> <& /Elements/SelectDate, Name => "Told_Date", ShowTime => 0, Default => '' &> </td></tr>
-<tr><td class="label"> <&|/l&>Make date Due</&>: </td>
-<td class="value"> <& /Elements/SelectDate, Name => "Due_Date", ShowTime => 0, Default => '' &> </td></tr>
-<tr><td class="label"> <&|/l&>Make date Resolved</&>: </td>
-<td class="value"> <& /Elements/SelectDate, Name => "Resolved_Date", ShowTime => 0, Default => '' &> </td></tr>
+<tr><td class=label> <&|/l&>Make subject</&>: </td>
+<td class=value> <INPUT Name="Subject" SIZE=20> </td></tr>
+<tr><td class=label> <&|/l&>Make priority</&>: </td>
+<td class=value> <INPUT Name="Priority" SIZE=4> </td></tr>
+<tr><td class=label> <&|/l&>Make queue</&>: </td>
+<td class=value> <& /Elements/SelectQueue, Name => "Queue" &> </td></tr>
+<tr><td class=label> <&|/l&>Make Status</&>: </td>
+<td class=value> <& /Elements/SelectStatus, Name => "Status" &> </td></tr>
+<tr><td class=label> <&|/l&>Make date Starts</&>: </td>
+<td class=value> <& /Elements/SelectDate, Name => "Starts_Date", ShowTime => 0, Default => '' &> </td></tr>
+<tr><td class=label> <&|/l&>Make date Started</&>: </td>
+<td class=value> <& /Elements/SelectDate, Name => "Started_Date", ShowTime => 0, Default => '' &> </td></tr>
+<tr><td class=label> <&|/l&>Make date Told</&>: </td>
+<td class=value> <& /Elements/SelectDate, Name => "Told_Date", ShowTime => 0, Default => '' &> </td></tr>
+<tr><td class=label> <&|/l&>Make date Due</&>: </td>
+<td class=value> <& /Elements/SelectDate, Name => "Due_Date", ShowTime => 0, Default => '' &> </td></tr>
+<tr><td class=label> <&|/l&>Make date Resolved</&>: </td>
+<td class=value> <& /Elements/SelectDate, Name => "Resolved_Date", ShowTime => 0, Default => '' &> </td></tr>
</table>
-</td>
-</tr>
+</TD>
+</TR>
</table>
-</&>
-<&| /Widgets/TitleBox, title => loc('Add comments or replies to selected tickets') &>
+<& /Elements/TitleBoxEnd&>
+<& /Elements/TitleBoxStart, title => loc('Add comments or replies to selected tickets') &>
<table>
-<tr><td align="right"><&|/l&>Update Type</&>:</td>
+<tr><td align=right><&|/l&>Update Type</&>:</td>
<td><select name="UpdateType">
<option value="private" ><&|/l&>Comments (not sent to requestors)</&></option>
<option value="response" ><&|/l&>Reply to requestors</&></option>
</select>
</td></tr>
-<tr><td align="right"><&|/l&>Subject</&>:</td><td> <input name="UpdateSubject" size="60" value="" /></td></tr>
+<tr><td align=right><&|/l&>Subject</&>:</td><td> <input name="UpdateSubject" size=60 value=""></td></tr>
% while (my $CF = $TxnCFs->Next()) {
-<tr>
-<td align="right"><% $CF->Name %>:</td>
-<td><& /Elements/EditCustomField,
+<TR>
+<TD ALIGN=RIGHT><% $CF->Name %>:</TD>
+<TD><& /Elements/EditCustomField,
CustomField => $CF,
NamePrefix => "Object-RT::Transaction--CustomField-"
- &><em><% $CF->FriendlyType %></em></td>
-</td></tr>
+ &><em><% $CF->FriendlyType %></em></TD>
+</TD></TR>
% } # end if while
- <tr><td align="right"><&|/l&>Attach</&>:</td><td><input name="UpdateAttachment" type="file" /></td></tr>
- <tr><td class="labeltop"><&|/l&>Message</&>:</td><td>
+ <tr><td align=right><&|/l&>Attach</&>:</td><td><input name="UpdateAttachment" type="file"></td></tr>
+ <tr><td class=labeltop><&|/l&>Message</&>:</td><td>
<& /Elements/MessageBox, Name=>"UpdateContent"&>
</td></tr>
</table>
-</&>
-<&|/Widgets/TitleBox, title => loc('Edit Custom Fields'), color => "#336633"&>
-<%perl>
-my $cfs = RT::CustomFields->new($session{'CurrentUser'});
-$cfs->LimitToGlobal();
-$cfs->LimitToQueue($_) for keys %$seen_queues;
-</%perl>
-<table>
-<tr>
-<th><&|/l&>Name</&></th>
-<th><&|/l&>Add values</&></th>
-<th><&|/l&>Delete values</&></th>
-</tr>
-% while (my $cf = $cfs->Next()) {
-<tr>
-<td class="label"><%$cf->Name%><br />
-<em>(<%$cf->FriendlyType%>)</em></td>
-% my $rows = 5;
-% my @add = (NamePrefix => 'Bulk-Add-CustomField-', CustomField => $cf, Rows => $rows, Multiple => ($cf->MaxValues ==1 ? 0 : 1) , Cols => 25);
-% my @del = (NamePrefix => 'Bulk-Delete-CustomField-', CustomField => $cf, Rows => $rows, Multiple => 1, Cols => 25);
-% if ($cf->Type eq 'Select') {
-<td><& /Elements/EditCustomFieldSelect, @add &></td>
-<td><& /Elements/EditCustomFieldSelect, @del &></td>
-% } elsif ($cf->Type eq 'Combobox') {
-<td><& /Elements/EditCustomFieldCombobox, @add &></td>
-<td><& /Elements/EditCustomFieldCombobox, @del &></td>
-% } elsif ($cf->Type eq 'Freeform') {
-<td><& /Elements/EditCustomFieldFreeform, @add &></td>
-<td><& /Elements/EditCustomFieldFreeform, @del &></td>
-% } elsif ($cf->Type eq 'Text') {
-<td><& /Elements/EditCustomFieldText, @add &></td>
-<td>&nbsp;</td>
-% } else {
-% $RT::Logger->crit("Unknown CustomField type: " . $cf->Type);
-% }
-</tr>
-% }
-</table>
-</&>
+<& /Elements/TitleBoxEnd &>
-<&|/Widgets/TitleBox, title => loc('Edit Links'), color => "#336633"&>
-<em><&|/l&>Enter tickets or URIs to link tickets to. Separate multiple entries with spaces.</&></em><br />
-<& /Ticket/Elements/BulkLinks &>
-</&>
-
-<& /Elements/Submit, Label => loc('Update') &>
+<& /Elements/TitleBoxStart, title => loc('Edit Links'), color => "#336633"&>
+<i><&|/l&>Enter tickets or URIs to link tickets to. Separate multiple entries with spaces.</&></i><br>
+<& /Ticket/Elements/BulkLinks &>
+<& /Elements/TitleBoxEnd &>
-</form>
+<& /Elements/Submit, Label => loc('Update All') &>
+</FORM>
<%INIT>
-my $title = loc("Update multiple tickets");
# Iterate through the ARGS hash and remove anything with a null value.
-map ( $ARGS{$_} =~ /^$/ && ( delete $ARGS{$_} ), keys %ARGS );
-
-my (@results);
-
-$Page ||= 1;
-
-$Format ||= $RT::DefaultSearchResultFormat;
-
-# inject _CHECKBOX to the first field.
-$Format =~ s/'?([^']+)'?,/'___CHECKBOX__$1',/;
-
-my $Tickets = RT::Tickets->new( $session{'CurrentUser'} );
-$Tickets->FromSQL($Query);
-if ( $OrderBy =~ /\|/ ) {
-
- # Multiple Sorts
- my @OrderBy = split /\|/, $OrderBy;
- my @Order = split /\|/, $Order;
- $Tickets->OrderByCols(
- map { { FIELD => $OrderBy[$_], ORDER => $Order[$_] } }
- ( 0 .. $#OrderBy ) );
-}
-else {
- $Tickets->OrderBy( FIELD => $OrderBy, ORDER => $Order );
-}
-
-$Tickets->RowsPerPage($Rows) if ($Rows);
-$Tickets->GotoPage( $Page - 1 ); # SB uses page 0 as the first page
-
-Abort( loc("No search to operate on.") ) unless ($Tickets);
-
-# build up a list of all custom fields for tickets that we're displaying, so
-# we can display sane edit widgets.
-
-my $fields = {};
-my $seen_queues = {};
-while ( my $ticket = $Tickets->Next ) {
- next if $seen_queues->{ $ticket->Queue }++;
-
- my $custom_fields = $ticket->QueueObj->TicketCustomFields;
- while ( my $field = $custom_fields->Next ) {
- $fields->{ $field->id } = $field;
+map ($ARGS{$_} =~ /^$/ && (delete $ARGS{$_}), keys %ARGS);
+
+my ($bgcolor, @results);
+my @cols = qw(id Status Priority Subject QueueObj->Name OwnerObj->Name RequestorAddresses DueAsString );
+
+
+my $Tickets = RT::Tickets->new($session{'CurrentUser'});
+$Tickets->FromSQL($ARGS{'Query'});
+
+Abort(loc("No search to operate on.")) unless ($Tickets);
+
+my %allcfs;
+my %cfqnames;
+my %cfqs;
+my $count = 0;
+while (my $Ticket = $Tickets->Next) {
+ my $cfq = $Ticket->QueueObj;
+ my $cfqid = $cfq->Id;
+ my $cfqn = $cfq->Name;
+ unless ( exists $cfqs{$cfqid} ) {
+ $cfqs{$cfqid} = 1;
+ $count++;
+ my $cfs = $cfq->TicketCustomFields;
+ while (my $cf = $cfs->Next) {
+ $allcfs{$cf->Id} = $cf;
+ $cfqnames{$cf->Id} = $cfqn;
+ }
}
}
-my $do_comment_reply = 0;
-
+my $do_comment_reply=0;
# Prepare for ticket updates
-if ($ARGS{'UpdateContent'}) {
- $ARGS{'UpdateContent'} =~ s/\r\n/\n/g;
- chomp( $ARGS{'UpdateContent'} );
-
- if ($ARGS{'UpdateContent'} ne ''
- && $ARGS{'UpdateContent'} ne "-- \n"
- . $session{'CurrentUser'}->UserObj->Signature ) {
- $do_comment_reply = 1;
- }
+$ARGS{'UpdateContent'} =~ s/\r\n/\n/g;
+chomp ($ARGS{'UpdateContent'}) ;
+
+if ($ARGS{'UpdateContent'} &&
+ $ARGS{'UpdateContent'} ne '' &&
+ $ARGS{'UpdateContent'} ne "-- \n" .
+ $session{'CurrentUser'}->UserObj->Signature) {
+ $do_comment_reply=1;
}
#Iterate through each ticket we've been handed
@@ -266,131 +229,50 @@ my @linkresults;
my %queues;
$Tickets->RedoSearch();
-
-# pull out the labels for any custom fields we want to update
-
-my $cf_del_keys;
-@$cf_del_keys = grep { /^Bulk-Delete-CustomField/ } keys %ARGS;
-my $cf_add_keys;
-@$cf_add_keys = grep { /^Bulk-Add-CustomField/ } keys %ARGS;
-
-
-while ( my $Ticket = $Tickets->Next ) {
- next unless ( $ARGS{ "UpdateTicket" . $Ticket->Id } );
-
- #Update the links
- $ARGS{'id'} = $Ticket->id;
- $queues{ $Ticket->QueueObj->Id }++;
-
- my @updateresults;
+while (my $Ticket = $Tickets->Next) {
+ $queues{$Ticket->QueueObj->Id}++;
+ $RT::Logger->debug( "Checking Ticket ".$Ticket->Id ."\n");
+ next unless ($ARGS{"UpdateTicket".$Ticket->Id});
+ $RT::Logger->debug ("Matched\n");
+ my @updateresults;
if ($do_comment_reply) {
- ProcessUpdateMessage(
- TicketObj => $Ticket,
- ARGSRef => \%ARGS,
- Actions => \@updateresults
- );
+ ProcessUpdateMessage(TicketObj => $Ticket, ARGSRef => \%ARGS, Actions => \@updateresults);
}
#Update the basics.
- my @basicresults =
- ProcessTicketBasics( TicketObj => $Ticket, ARGSRef => \%ARGS );
- my @dateresults =
- ProcessTicketDates( TicketObj => $Ticket, ARGSRef => \%ARGS );
-
+ my @basicresults = ProcessTicketBasics(TicketObj => $Ticket, ARGSRef => \%ARGS);
+ my @dateresults = ProcessTicketDates(TicketObj => $Ticket, ARGSRef => \%ARGS);
#Update the watchers
- my @watchresults =
- ProcessTicketWatchers( TicketObj => $Ticket, ARGSRef => \%ARGS );
+ my @watchresults = ProcessTicketWatchers(TicketObj => $Ticket, ARGSRef => \%ARGS);
- foreach my $type qw(MergeInto DependsOn MemberOf RefersTo) {
- $ARGS{ $Ticket->id . "-" . $type } = $ARGS{"Ticket-$type"};
- $ARGS{ $type . "-" . $Ticket->id } = $ARGS{"$type-Ticket"};
- }
- @linkresults =
- ProcessTicketLinks( TicketObj => $Ticket, ARGSRef => \%ARGS );
- foreach my $type qw(MergeInto DependsOn MemberOf RefersTo) {
- delete $ARGS{ $type . "-" . $Ticket->id };
- delete $ARGS{ $Ticket->id . "-" . $type };
- }
-
- my @cfresults;
-
- foreach my $list ( $cf_add_keys, $cf_del_keys ) {
- next unless $list->[0];
-
-
- my $op;
- if ( $list->[0] =~ /Add/ ) {
- $op = 'add';
-
- }
- elsif ( $list->[0] =~ /Del/ ) {
- $op = 'del';
- }
- else {
- $RT::Logger->crit(
- "Got an op that was neither add nor delete. can never happen"
- . $list->[0] );
- last;
- }
-
- foreach my $key (@$list) {
- my ( $cfid, $cf );
- if ( $key =~ /CustomField-(\d+)-/ ) {
- $cfid = $1;
- $cf = RT::CustomField->new( $session{'CurrentUser'} );
- $cf->Load($cfid);
- }
- else {next}
- my @values =
- ref( $ARGS{$key} ) eq 'ARRAY'
- ? @{ $ARGS{$key} }
- : ( $ARGS{$key} );
- map { s/(\r\n|\r)/\n/g; } @values; # fix the newlines
- # now break the multiline values into multivalues
- @values = map { split( /\n/, $_ ) } @values
- unless ( $cf->SingleValue );
-
- my $current_values = $Ticket->CustomFieldValues($cfid);
- foreach my $value (@values) {
- if ( $op eq 'del' && $current_values->HasEntry($value) ) {
- my ( $id, $msg ) = $Ticket->DeleteCustomFieldValue(
- Field => $cfid,
- Value => $value
- );
- push @cfresults, $msg;
- }
-
- elsif ( $op eq 'add' && !$current_values->HasEntry($value) ) {
- my ( $id, $msg ) = $Ticket->AddCustomFieldValue(
- Field => $cfid,
- Value => $value
- );
- push @cfresults, $msg;
- }
- }
- }
- }
- my @tempresults = (
- @watchresults, @basicresults, @dateresults,
- @updateresults, @linkresults, @cfresults
- );
-
- @tempresults =
- map { loc( "Ticket [_1]: [_2]", $Ticket->Id, $_ ) } @tempresults;
- @results = ( @results, @tempresults );
+ #Update the links
+ $ARGS{'id'} = $Ticket;
+ $ARGS{$Ticket->Id.'-MergeInto'} = $ARGS{'Ticket-MergeInto'};
+ $ARGS{$Ticket->Id.'-DependsOn'} = $ARGS{'Ticket-DependsOn'};
+ $ARGS{'DependsOn-'.$Ticket->Id} = $ARGS{'DependsOn-Ticket'};
+ $ARGS{$Ticket->Id.'-MemberOf'} = $ARGS{'Ticket-MemberOf'};
+ $ARGS{'MemberOf-'.$Ticket->Id} = $ARGS{'MemberOf-Ticket'};
+ $ARGS{$Ticket->Id.'-RefersTo'} = $ARGS{'Ticket-RefersTo'};
+ $ARGS{'RefersTo-'.$Ticket->Id} = $ARGS{'RefersTo-Ticket'};
+ @linkresults = ProcessTicketLinks( TicketObj => $Ticket, ARGSRef => \%ARGS);
+ delete $ARGS{'id'};
+ delete $ARGS{$Ticket->Id.'-MergeInto'};
+ delete $ARGS{$Ticket->Id.'-DependsOn'};
+ delete $ARGS{'DependsOn-'.$Ticket->Id};
+ delete $ARGS{$Ticket->Id.'-MemberOf'};
+ delete $ARGS{'MemberOf-'.$Ticket->Id};
+ delete $ARGS{$Ticket->Id.'-RefersTo'};
+ delete $ARGS{'RefersTo-'.$Ticket->Id};
+ my @tempresults = (@watchresults, @basicresults, @dateresults,
+ @updateresults, @linkresults);
+ @tempresults = map { loc("Ticket [_1]: [_2]",$Ticket->Id,$_) } @tempresults;
+
+ @results = (@results, @tempresults);
}
-my $TxnCFs = RT::CustomFields->new( $session{CurrentUser} );
-$TxnCFs->LimitToLookupType( RT::Transaction->CustomFieldLookupType );
-$TxnCFs->LimitToGlobalOrObjectId( sort keys %queues );
+my $TxnCFs = RT::CustomFields->new($session{CurrentUser});
+$TxnCFs->LimitToLookupType("RT::Queue-RT::Ticket-RT::Transaction");
+$TxnCFs->LimitToGlobalOrObjectId(sort keys %queues);
</%INIT>
-<%args>
-$Format => undef
-$Page => 1
-$Rows => undef
-$Order => 'ASC'
-$OrderBy => 'id'
-$Query => undef
-</%args>
diff --git a/rt/html/Search/Elements/PickRestriction b/rt/html/Search/Elements/PickRestriction
deleted file mode 100644
index ff9b86ba5..000000000
--- a/rt/html/Search/Elements/PickRestriction
+++ /dev/null
@@ -1,142 +0,0 @@
-%# BEGIN LICENSE BLOCK
-%#
-%# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com>
-%#
-%# (Except where explictly superceded by other copyright notices)
-%#
-%# 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.
-%#
-%# Unless otherwise specified, all modifications, corrections or
-%# extensions to this work which alter its source code become the
-%# property of Best Practical Solutions, LLC when submitted for
-%# inclusion in the work.
-%#
-%#
-%# END LICENSE BLOCK
-<FORM ACTION="<%$RT::WebPath%>/Search/Listing.html" METHOD="GET">
-<INPUT TYPE=HIDDEN NAME="Bookmark" VALUE="<% $session{'tickets'}->FreezeLimits()%>">
-<& /Elements/TitleBoxStart, title => loc('Refine search')&>
-<INPUT TYPE=HIDDEN NAME="CompileRestriction" VALUE=1>
-
-<ul>
-<li><&|/l&>Owner is</&> <& /Elements/SelectBoolean, Name => "OwnerOp",
- TrueVal=> '=',
- FalseVal => '!='
-&>
-<& /Elements/SelectOwner, Name => "ValueOfOwner" &>
-
-<li>
-<& /Elements/SelectWatcherType, Name => "WatcherRole", AllowNull => 0 &>
-<&|/l&>email address</&>
-<& /Elements/SelectMatch, Name => "WatcherRoleOp" &>
-<INPUT Name="ValueOfWatcherRole" SIZE=20>
-
-<li>
-<&|/l&>Subject</&> <& /Elements/SelectMatch, Name => "SubjectOp" &>
-<INPUT Name="ValueOfSubject" SIZE=20>
-
-<li><&|/l&>Queue</&> <& /Elements/SelectBoolean, Name => "QueueOp" ,
- True => loc("is"),
- False => loc("isn't"),
- TrueVal=> '=',
- FalseVal => '!=' &>
-<& /Elements/SelectQueue, Name => "ValueOfQueue" &>
-
-
-<li><&|/l&>Priority</&> <& /Elements/SelectEqualityOperator, Name => "PriorityOp" &>
-
-<INPUT Name="ValueOfPriority" SIZE=5>
-
-<li>
-<& /Elements/SelectDateType, Name => 'DateType' &>
-<& /Elements/SelectDateRelation, Name=>"DateOp" &>
-<& /Elements/SelectDate, Name => "ValueOfDate", ShowTime => 0, Default => '' &>
-
-<li><&|/l&>Ticket attachment</&>
-
-<& /Elements/SelectAttachmentField, Name => 'AttachmentField' &>
-<& /Elements/SelectBoolean, Name => "AttachmentFieldOp",
- True => loc("matches"),
- False => loc("does not match"),
- TrueVal => 'LIKE',
- FalseVal => 'NOT LIKE'
-&>
-<Input Name="ValueOfAttachmentField" Size=20>
-
-<li><&|/l&>Status</&>
-<& /Elements/SelectBoolean, Name => "StatusOp",
- True => loc("is"),
- False => loc("isn't"),
- TrueVal=> '=',
- FalseVal => '!='
-&>
-<& /Elements/SelectStatus, Name => "ValueOfStatus", SkipDeleted => 1 &>
-
-
-% while ( my $CustomField = $CustomFields->Next ) {
-
-<li><% $CustomField->Name %>
- <& /Elements/SelectCustomFieldOperator, Name => "CustomFieldOp". $CustomField->id,
- True => loc("is"),
- False => loc("isn't"),
- TrueVal=> '=', FalseVal => '!=' &>
-
-<& /Elements/SelectCustomFieldValue, Name => "CustomField".$CustomField->id,
- CustomField => $CustomField,
- &>
-% }
-
-</UL>
-
-<& /Elements/TitleBoxEnd &>
-
-<& /Elements/TitleBoxStart, title => loc('Ordering and sorting')&>
-
-<UL>
-
-<li><&|/l&>Results per page</&> <& /Elements/SelectResultsPerPage, Name => "RowsPerPage",
- Default => $session{'tickets_rows_per_page'} || '50'
-&>
-
-<li><&|/l&>Sort results by</&> <& /Elements/SelectTicketSortBy, Name => "TicketsSortBy",
- Default => $session{'tickets_sort_by'}
-&>
-<& /Elements/SelectSortOrder, Name => 'TicketsSortOrder', Default => $session{'tickets_sort_order'} &>
-
-<li><input type="checkbox" name="HideResults" <%$ARGS{'HideResults'} && 'CHECKED'%>> <&|/l&>Don't show search results</&>
-<li><& /Elements/Refresh, Name => 'RefreshSearchInterval' , Default => $session{'tickets_refresh_interval'} &>
-
-</UL>
-
-
-</DIV>
-
-
-
-<& /Elements/TitleBoxEnd &>
-
-<& /Elements/Submit, Label => loc('Search'), Name => 'Action'&>
-
-</FORM>
-
-
- <%INIT>
-my $CustomFields = RT::CustomFields->new( $session{'CurrentUser'});
- foreach ( $session{'tickets'}->RestrictionValues('Queue') ) {
- # Gotta load up the $queue object, since queues get stored by name now.
- my $queue = RT::Queue->new($session{'CurrentUser'});
- $queue->Load($_);
- $CustomFields->LimitToQueue($queue->Id);
- }
-
- $CustomFields->LimitToGlobal();
-
-</%INIT>
diff --git a/rt/html/Search/Elements/TicketHeader b/rt/html/Search/Elements/TicketHeader
deleted file mode 100644
index ed2f60e4e..000000000
--- a/rt/html/Search/Elements/TicketHeader
+++ /dev/null
@@ -1,40 +0,0 @@
-%# BEGIN LICENSE BLOCK
-%#
-%# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com>
-%#
-%# (Except where explictly superceded by other copyright notices)
-%#
-%# 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.
-%#
-%# Unless otherwise specified, all modifications, corrections or
-%# extensions to this work which alter its source code become the
-%# property of Best Practical Solutions, LLC when submitted for
-%# inclusion in the work.
-%#
-%#
-%# END LICENSE BLOCK
-<TR>
-<& TicketHeaderCell , Attribute => 'id', Header => '#'&>
-<& TicketHeaderCell , Attribute => 'Subject'&>
-<& TicketHeaderCell , Attribute => 'Status'&>
-<& TicketHeaderCell , Attribute => 'Queue'&>
-<& TicketHeaderCell , Attribute => 'Owner'&>
-<& TicketHeaderCell , Attribute => 'Priority'&>
-</TR>
-<TR>
-<TH class="ticketheader">&nbsp;</TH>
-<& TicketHeaderCell , Attribute => 'Requestor(s)'&>
-<& TicketHeaderCell , Attribute => 'Created'&>
-<& TicketHeaderCell , Attribute => 'Told', Header => 'Last Contact'&>
-<& TicketHeaderCell , Attribute => 'LastUpdated', Header => 'Last Updated'&>
-<& TicketHeaderCell , Attribute => 'TimeLeft', Header => 'Left'&>
-</TR>
-%# loc('Last Notified');
diff --git a/rt/html/Search/Elements/TicketHeaderCell b/rt/html/Search/Elements/TicketHeaderCell
deleted file mode 100644
index 5def9ea37..000000000
--- a/rt/html/Search/Elements/TicketHeaderCell
+++ /dev/null
@@ -1,55 +0,0 @@
-%# BEGIN LICENSE BLOCK
-%#
-%# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com>
-%#
-%# (Except where explictly superceded by other copyright notices)
-%#
-%# 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.
-%#
-%# Unless otherwise specified, all modifications, corrections or
-%# extensions to this work which alter its source code become the
-%# property of Best Practical Solutions, LLC when submitted for
-%# inclusion in the work.
-%#
-%#
-%# END LICENSE BLOCK
-<%INIT>
-my ($order,$curorder);
- $Attribute =~ s/Obj->(Name|AsString|AgeAsString)//g;
- if ($session{'tickets_sort_order'} =~ /^asc$/i) {
- $order = 'DESC';
- $curorder = 'ASC';
- } else {
- $order = 'ASC';
- $curorder = 'DESC';
- }
-$Header = $Attribute unless ($Header);
-
-</%INIT>
-<th class="ticketheader">
-% if (grep (/^$Attribute$/i, $session{'tickets'}->SortFields)) {
-<A
-% if ($Attribute eq $session{'tickets_sort_by'}) {
-class="currenttab"
-HREF="<% $RT::WebPath%>/Search/Listing.html?Bookmark=<%$session{'tickets'}->FreezeLimits()|u%>&TicketsSortBy=<%$Attribute%>&TicketsSortOrder=<%$order%>&RowsPerPage=<%$session{'tickets_rows_per_page'}%>">
-% } else {
-HREF="<% $RT::WebPath%>/Search/Listing.html?Bookmark=<%$session{'tickets'}->FreezeLimits()|u%>&TicketsSortBy=<%$Attribute%>&TicketsSortOrder=<%$curorder%>&RowsPerPage=<%$session{'tickets_rows_per_page'}%>">
-% }
-<% loc($Header) %>
-</A>
-% } else {
-<% loc($Header) %>
-% }
-</th>
-<%ARGS>
-$Header => undef
-$Attribute => undef
-</%ARGS>
diff --git a/rt/html/Search/Elements/TicketRow b/rt/html/Search/Elements/TicketRow
deleted file mode 100644
index 5d1ad209a..000000000
--- a/rt/html/Search/Elements/TicketRow
+++ /dev/null
@@ -1,55 +0,0 @@
-%# BEGIN LICENSE BLOCK
-%#
-%# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com>
-%#
-%# (Except where explictly superceded by other copyright notices)
-%#
-%# 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.
-%#
-%# Unless otherwise specified, all modifications, corrections or
-%# extensions to this work which alter its source code become the
-%# property of Best Practical Solutions, LLC when submitted for
-%# inclusion in the work.
-%#
-%#
-%# END LICENSE BLOCK
-<SPAN class="search">
-<TR
-% if ($i%2) {
-CLASS="oddline"
-% } else {
-CLASS="evenline"
-% }
->
-<TD ROWSPAN="2"><B><A HREF="<%$RT::WebPath%>/Ticket/Display.html?id=<%$Ticket->Id%>"><%$Ticket->id%></a></B></TD>
-<TD><B><A HREF="<%$RT::WebPath%>/Ticket/Display.html?id=<%$Ticket->Id%>"><%$Ticket->Subject%></a></B></TD>
-<TD><%loc($Ticket->Status)%></TD>
-<TD><%$Ticket->QueueObj->Name%></TD>
-<TD><%$Ticket->Owner == $RT::Nobody->Id ? loc('Nobody') : $Ticket->OwnerObj->Name%></TD>
-<TD><%$Ticket->Priority%></TD>
-</TR>
-<TR
-% if ($i%2) {
-CLASS="oddline"
-% } else {
-CLASS="evenline"
-% }
-><TD><small><%$Ticket->Requestors->MemberEmailAddressesAsString%></small></TD>
-<TD><SMALL><%$Ticket->CreatedObj->AgeAsString || '-'%></SMALL></TD>
-<TD><SMALL><%$Ticket->ToldObj->AgeAsString || '-'%></SMALL></TD>
-<TD><SMALL><%$Ticket->LastUpdatedObj->AgeAsString || '-'%></SMALL></TD>
-<TD><SMALL><%$Ticket->TimeLeft%></SMALL></TD>
-</TR>
-</SPAN>
-<%ARGS>
-$Ticket => undef
-$i => undef
-</%ARGS>
diff --git a/rt/html/Search/Listing.html b/rt/html/Search/Listing.html
deleted file mode 100644
index 68b1fd75c..000000000
--- a/rt/html/Search/Listing.html
+++ /dev/null
@@ -1,113 +0,0 @@
-%# BEGIN LICENSE BLOCK
-%#
-%# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com>
-%#
-%# (Except where explictly superceded by other copyright notices)
-%#
-%# 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.
-%#
-%# Unless otherwise specified, all modifications, corrections or
-%# extensions to this work which alter its source code become the
-%# property of Best Practical Solutions, LLC when submitted for
-%# inclusion in the work.
-%#
-%#
-%# END LICENSE BLOCK
-<& /Elements/Header, Title => $title, Refresh => $session{'tickets_refresh_interval'} &>
-<& /Ticket/Elements/Tabs,
- current_tab => 'Search/Listing.html',
- Title => $title &>
-
-%if ($ticketcount && ! $ARGS{'HideResults'}) {
-<TABLE WIDTH=100% border=0 cellpadding=2 CELLSPACING=0>
-<& Elements/TicketHeader, %ARGS &>
-% my $i;
-%while (my $Ticket = $session{'tickets'}->Next) {
-% $i++;
-<& Elements/TicketRow, Ticket => $Ticket, i=> $i, %ARGS &>
-%}
-</TABLE>
-<div align=center>
-<font size=2>
-<a href="<%$RT::WebPath%>/Search/Listing.html?GotoPage=1"><&|/l&>First page</&></a>
-&nbsp;&nbsp;
-% if ( $session{'tickets'}->FirstRow >= $session{'tickets_rows_per_page'}-1 ) {
-<a href="<%$RT::WebPath%>/Search/Listing.html?GotoPage=Prev">&lt;<&|/l&>Previous page</&></a>
-&nbsp;&nbsp;
-% }
-% if ( $session{'tickets'}->FirstRow + $session{'tickets_rows_per_page'} < $ticketcount ) {
-<a href="<%$RT::WebPath%>/Search/Listing.html?GotoPage=Next"><&|/l&>Next page</&>&gt;</a>
-% }
-%#&nbsp;&nbsp;<form method=get action="<%$RT::WebPath%>/Search/Listing.html"><&|/l&>Goto page</&> <input name=GotoPage size=2></form>
-</font>
-</div>
-<!--<div align=right>-->
-<table width="100%" border=0 cellpadding=3 CELLSPACING=1>
-<tr>
-<td align=left>
-(<&|/l, ($session{'tickets'}->FirstRow+1), ($session{'tickets'}->FirstRow() + $session{'tickets'}->RowsPerPage() ) &>[_1] - [_2] shown</&>)
-</td>
-<td align=right>
-
-<a href="<%$RT::WebPath%>/Search/Bulk.html"><&|/l&>Update all these tickets at once</&></a>
-<!--</div>-->
-</td>
-</tr>
-</table>
-
-% }
-<TABLE WIDTH="100%">
-<TR>
-<TD VALIGN="TOP">
-<& /Elements/TitleBoxStart, title => loc('Current search criteria')&>
-
-%my %restrictions=$session{'tickets'}->DescribeRestrictions();
-%foreach my $row (keys %restrictions){
-<%$restrictions{"$row"}%> <A HREF="<% $RT::WebPath %>/Search/Listing.html?DeleteRestriction=<%$row%>">[<&|/l&>delete</&>]</a><br>
-%}
-<BR>
-<BR>
-<A HREF="<% $RT::WebPath%>/Search/Listing.html?Bookmark=<%$session{'tickets'}->FreezeLimits()|nu%>&TicketsSortBy=<%$session{'tickets_sort_by'}%>&TicketsSortOrder=<%$session{'tickets_sort_order'}%>&RowsPerPage=<%$session{'tickets_rows_per_page'}%>"><&|/l&>Bookmarkable URL for this search</&></a>
-<& /Elements/TitleBoxEnd&>
-</TD>
-<TD>
-
-<& Elements/PickRestriction, %ARGS &>
-
-</TD>
-</TR>
-</TABLE>
-
-<%INIT>
-
-my ($title, $ticketcount);
-$session{'i'}++;
-if ($session{'tickets'}) {
- if ($ARGS{'DeleteRestriction'}) {
- $session{'tickets'}->DeleteRestriction($ARGS{'DeleteRestriction'});
- }
- if ( ($ARGS{'ClearRestrictions'}) || ($ARGS{'NewSearch'}) ) {
- $session{'tickets'}->ClearRestrictions;
- $session{'tickets'}->CleanSlate;
- }
-}
- ProcessSearchQuery(ARGS=>\%ARGS);
- $session{'tickets'}->RedoSearch();
- if ( $session{'tickets'}->DescribeRestrictions()) {
- $ticketcount = $session{tickets}->CountAll();
- $title = loc('Found [quant,_1,ticket]', $ticketcount);
- } else {
- $title = loc("Find tickets");
- }
-</%INIT>
-<%CLEANUP>
-$session{'tickets'}->PrepForSerialization();
-</%CLEANUP>
diff --git a/rt/html/Ticket/Elements/AddCustomers b/rt/html/Ticket/Elements/AddCustomers
new file mode 100644
index 000000000..01c7367c4
--- /dev/null
+++ b/rt/html/Ticket/Elements/AddCustomers
@@ -0,0 +1,50 @@
+%# Copyright (c) 2004 Ivan Kohler <ivan-rt@420.am>
+%#
+%# 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.
+<BR>
+<%$msg%><br>
+
+% if (@Customers) {
+
+<br><i>(Check box to link)<i>
+<table>
+% foreach my $customer (@Customers) {
+<tr>
+ <td>
+ <input type="checkbox" name="Ticket-AddCustomer-<% $customer->{'custnum'} %>" VALUE="1" <% scalar(@Customers) == 1 ? 'CHECKED' : '' %>>
+ <A HREF="<%$freeside_url%>/view/cust_main.cgi?<% $customer->{'custnum'} %>"><% &RT::URI::freeside::small_custview($customer->{'custnum'}, &RT::URI::freeside::FreesideGetConfig('countrydefault'), 1) |n %>
+ </td>
+</tr>
+% }
+
+% }
+
+<%INIT>
+my ($msg);
+
+my $freeside_url = &RT::URI::freeside::FreesideURL();
+
+my @Customers = ();
+if ( $CustomerString ) {
+ @Customers = &RT::URI::freeside::smart_search( 'search' => $CustomerString );
+}
+
+my @Services = ();
+if ($ServiceString) {
+ @Services = (); #service_search();
+}
+
+</%INIT>
+
+<%ARGS>
+$CustomerString => undef
+$ServiceString => undef
+</%ARGS>
diff --git a/rt/html/Ticket/Elements/EditCustomers b/rt/html/Ticket/Elements/EditCustomers
new file mode 100644
index 000000000..c5a6f708c
--- /dev/null
+++ b/rt/html/Ticket/Elements/EditCustomers
@@ -0,0 +1,67 @@
+%# Copyright (c) 2004 Ivan Kohler <ivan-rt@420.am>
+%#
+%# 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.
+<TABLE width=100%>
+ <TR>
+ <TD VALIGN=TOP WIDTH=50%>
+ <h3><&|/l&>Current Customers</&></h3>
+
+<table>
+ <tr>
+ <td><i><&|/l&>(Check box to disassociate)</&></i></td>
+ </tr>
+ <tr>
+ <td class="value">
+% #while (my $link = $Ticket->MemberOf->Next) {
+% foreach my $link (
+% grep { $_->TargetURI->Resolver->{'fstable'} eq 'cust_main' }
+% grep { $_->TargetURI->Scheme eq 'freeside' }
+% @{ $Ticket->_Links('Base')->ItemsArrayRef }
+% ) {
+
+ <INPUT TYPE=CHECKBOX NAME="DeleteLink--<%$link->Type%>-<%$link->Target%>">
+%# <& ShowLink, URI => $link->TargetURI &><br>
+ <A HREF="<% $link->TargetURI->Resolver->HREF %>"><% $link->TargetURI->Resolver->AsStringLong |n %></A>
+ <BR>
+% }
+ </td>
+ </tr>
+</table>
+
+</TD>
+
+<TD VALIGN=TOP>
+<h3><&|/l&>New Customer Links</&></h3>
+<&|/l&>Find customer</&><BR>
+<input name="CustomerString">
+<input type=submit name="OnlySearchForCustomers" value="<&|/l&>Go!</&>">
+<br><i>cust #, name, company or phone</i>
+<BR>
+%#<BR>
+%#<&|/l&>Find service</&><BR>
+%#<input name="ServiceString">
+%#<input type=submit name="OnlySearchForServices" value="<&|/l&>Go!</&>">
+%#<br><i>username, username@domain, domain, or IP address</i>
+%#<BR>
+
+<& AddCustomers, Ticket => $Ticket,
+ CustomerString => $CustomerString,
+ ServiceString => $ServiceString, &>
+
+</TD>
+</TR>
+</TABLE>
+
+<%ARGS>
+$CustomerString => undef
+$ServiceString => undef
+$Ticket => undef
+</%ARGS>
diff --git a/rt/html/Ticket/Elements/EditLinks b/rt/html/Ticket/Elements/EditLinks
deleted file mode 100644
index bdb8a6b7d..000000000
--- a/rt/html/Ticket/Elements/EditLinks
+++ /dev/null
@@ -1,133 +0,0 @@
-%# BEGIN LICENSE BLOCK
-%#
-%# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com>
-%#
-%# (Except where explictly superceded by other copyright notices)
-%#
-%# 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.
-%#
-%# Unless otherwise specified, all modifications, corrections or
-%# extensions to this work which alter its source code become the
-%# property of Best Practical Solutions, LLC when submitted for
-%# inclusion in the work.
-%#
-%#
-%# END LICENSE BLOCK
-<TABLE width=100%>
- <TR>
- <TD VALIGN=TOP WIDTH=50%>
- <h3><&|/l&>Current Relationships</&></h3>
-
-<table>
- <tr>
- <td></td>
- <td><i><&|/l&>(Check box to delete)</&></i></td>
- </tr>
- <tr>
- <td class="labeltop"><&|/l&>Depends on</&>:</td>
- <td class="value">
-% while (my $link = $Ticket->DependsOn->Next) {
- <INPUT TYPE=CHECKBOX NAME="DeleteLink--<%$link->Type%>-<%$link->Target%>">
- <& ShowLink, URI => $link->TargetURI &><br>
-% }
- </td>
- </tr>
- <tr>
- <td class="labeltop"><&|/l&>Depended on by</&>:</td>
- <td class="value">
-% while (my $link = $Ticket->DependedOnBy->Next) {
-% my $member = $link->BaseObj;
- <INPUT TYPE=CHECKBOX NAME="DeleteLink-<%$link->Base%>-<%$link->Type%>-">
- <& ShowLink, URI => $link->BaseURI &><br>
-% }
- </td>
- </tr>
- <tr>
- <td class="labeltop"><&|/l&>Parents</&>:</td>
- <td class="value">
-% while (my $link = $Ticket->MemberOf->Next) {
- <INPUT TYPE=CHECKBOX NAME="DeleteLink--<%$link->Type%>-<%$link->Target%>">
- <& ShowLink, URI => $link->TargetURI &><br>
-% }
- </td>
- </tr>
- <tr>
- <td class="labeltop"><&|/l&>Children</&>:</td>
- <td class="value">
-% while (my $link = $Ticket->Members->Next) {
- <INPUT TYPE=CHECKBOX NAME="DeleteLink-<%$link->Base%>-<%$link->Type%>-">
- <& ShowLink, URI => $link->BaseURI &><br>
-% }
- </td>
- </tr>
- <tr>
- <td class="labeltop"><&|/l&>Refers to</&>:</td>
- <td class="value">
-% while (my $link = $Ticket->RefersTo->Next) {
- <INPUT TYPE=CHECKBOX NAME="DeleteLink--<%$link->Type%>-<%$link->Target%>">
- <& ShowLink, URI => $link->TargetURI &><br>
-%}
- </td>
- </tr>
- <tr>
- <td class="labeltop"><&|/l&>Referred to by</&>:</td>
- <td class="value">
-% while (my $link = $Ticket->ReferredToBy->Next) {
- <INPUT TYPE=CHECKBOX NAME="DeleteLink-<%$link->Base%>-<%$link->Type%>-">
- <& ShowLink, URI => $link->BaseURI &><br>
-% }
- </td>
- </tr>
-</table>
-
-</TD>
-<TD VALIGN=TOP>
-<h3><&|/l&>New Relationships</&></h3>
-<i><&|/l&>Enter tickets or URIs to link tickets to. Seperate multiple entries with spaces.</&></i><br>
-<TABLE>
- <TR>
- <TD class="label"><&|/l&>Merge into</&>:</TD>
- <TD class="entry"><input name="<%$Ticket->Id%>-MergeInto"> <i><&|/l&>(only one ticket)</&></i></TD>
- </TR>
- <TR>
- <TD class="label"><&|/l&>Depends on</&>:</TD>
- <TD class="entry"><input name="<%$Ticket->Id%>-DependsOn"></TD>
- </TR>
- <TR>
- <TD class="label"><&|/l&>Depended on by</&>:</TD>
- <TD class="entry"><input name="DependsOn-<%$Ticket->Id%>"></TD>
- </TR>
- <TR>
- <TD class="label"><&|/l&>Parents</&>:</TD>
- <TD class="entry"><input name="<%$Ticket->Id%>-MemberOf"></TD>
- </TR>
- <TR>
- <TD class="label"><&|/l&>Children</&>:</TD>
- <TD class="entry"> <input name="MemberOf-<%$Ticket->Id%>"></TD>
- </TR>
- <TR>
- <TD class="label"><&|/l&>Refers to</&>:</TD>
- <TD class="entry"><input name="<%$Ticket->Id%>-RefersTo"></TD>
- </TR>
- <TR>
- <TD class="label"><&|/l&>Referred to by</&>:</TD>
- <TD class="entry"> <input name="RefersTo-<%$Ticket->Id%>"></TD>
- </TR>
-</TABLE>
-</TD>
-</TR>
-</TABLE>
-
-
-
-<%ARGS>
-$Ticket => undef
-</%ARGS>
diff --git a/rt/html/Ticket/Elements/ShowCustomers b/rt/html/Ticket/Elements/ShowCustomers
new file mode 100644
index 000000000..612727ede
--- /dev/null
+++ b/rt/html/Ticket/Elements/ShowCustomers
@@ -0,0 +1,40 @@
+%# Copyright (c) 2004 Ivan Kohler <ivan-rt@420.am>
+%#
+%# 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.
+<table>
+% my $cust = 0;
+% foreach my $customerURI (
+% grep { $_->Resolver->{'fstable'} eq 'cust_main' }
+% grep { $_->Scheme eq 'freeside' }
+% map { $_->TargetURI }
+% @{ $Ticket->_Links('Base')->ItemsArrayRef }
+% ) {
+% $cust++;
+% my $cust_main = '';
+ <tr>
+ <td class="value">
+ <A HREF="<% $customerURI->Resolver->HREF %>"><% $customerURI->Resolver->AsStringLong |n %></A>
+ </td>
+ </tr>
+% }
+% unless ( $cust ) {
+ <tr>
+ <td class="labeltop">
+ <i>(none)<i>
+ </td>
+ </tr>
+
+% }
+</table>
+<%ARGS>
+$Ticket => undef
+</%ARGS>
+
diff --git a/rt/html/Ticket/Elements/ShowLink b/rt/html/Ticket/Elements/ShowLink
deleted file mode 100644
index 493fd95a5..000000000
--- a/rt/html/Ticket/Elements/ShowLink
+++ /dev/null
@@ -1,40 +0,0 @@
-%# BEGIN LICENSE BLOCK
-%#
-%# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com>
-%#
-%# (Except where explictly superceded by other copyright notices)
-%#
-%# 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.
-%#
-%# Unless otherwise specified, all modifications, corrections or
-%# extensions to this work which alter its source code become the
-%# property of Best Practical Solutions, LLC when submitted for
-%# inclusion in the work.
-%#
-%#
-%# END LICENSE BLOCK
-<A href="<%$URI->Resolver->HREF%>">
-% if ($URI->IsLocal) {
-% my $member = $URI->Object;
-% if (UNIVERSAL::isa($member, "RT::Ticket")) {
-<%$member->Id%>: (<%$member->OwnerObj->Name%>) <%$member->Subject%> [<% loc($member->Status) %>]
-% } elsif ( UNIVERSAL::can($member, 'Name')) {
-<%$URI->Resolver->AsString%>: <%$member->Name%>
-% } else {
-<%$URI->Resolver->AsString%>
-% }
-% } else {
-<%$URI->Resolver->AsString%>
-% }
-</a>
-<%ARGS>
-$URI => undef
-</%ARGS>
diff --git a/rt/html/Ticket/Elements/ShowLinks b/rt/html/Ticket/Elements/ShowLinks
deleted file mode 100644
index f88a6008d..000000000
--- a/rt/html/Ticket/Elements/ShowLinks
+++ /dev/null
@@ -1,87 +0,0 @@
-%# BEGIN LICENSE BLOCK
-%#
-%# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com>
-%#
-%# (Except where explictly superceded by other copyright notices)
-%#
-%# 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.
-%#
-%# Unless otherwise specified, all modifications, corrections or
-%# extensions to this work which alter its source code become the
-%# property of Best Practical Solutions, LLC when submitted for
-%# inclusion in the work.
-%#
-%#
-%# END LICENSE BLOCK
-<table>
- <tr>
- <td class="labeltop"><&|/l&>Depends on</&>:</td>
- <td class="value">
-<ul>
-% while (my $Link = $Ticket->DependsOn->Next) {
-<li><& ShowLink, URI => $Link->TargetURI &>
-% }
-</ul>
- </td>
- </tr>
- <tr>
- <td class="labeltop"><&|/l&>Depended on by</&>:</td>
- <td class="value">
-<ul>
-% while (my $Link = $Ticket->DependedOnBy->Next) {
-<li><& ShowLink, URI => $Link->BaseURI &>
-% }
-</ul>
- </td>
- </tr>
- <tr>
- <td class="labeltop"><&|/l&>Parents</&>:</td>
- <td class="value">
-<ul>
-% while (my $Link = $Ticket->MemberOf->Next) {
-<li><& ShowLink, URI => $Link->TargetURI &>
-% }
-</ul>
- </td>
- </tr>
- <tr>
- <td class="labeltop"><&|/l&>Children</&>:</td>
- <td class="value"><& /Ticket/Elements/ShowMembers, Ticket => $Ticket &></td>
- </tr>
- <tr>
- <td class="labeltop"><&|/l&>Refers to</&>:</td>
- <td class="value">
-<ul>
-% while (my $Link = $Ticket->RefersTo->Next) {
-<li><& ShowLink, URI => $Link->TargetURI &>
-% }
-</ul>
- </td>
- </tr>
- <tr>
- <td class="labeltop"><&|/l&>Referred to by</&>:</td>
- <td class="value">
- <ul>
-% while (my $Link = $Ticket->ReferredToBy->Next) {
-<li><& ShowLink, URI => $Link->BaseURI &>
-% }
-</ul>
- </td>
- </tr>
-
-% # Allow people to add more rows to the table
-% $m->comp('/Elements/Callback', %ARGS );
-
-</table>
-
-<%ARGS>
-$Ticket => undef
-</%ARGS>
diff --git a/rt/html/Ticket/Elements/ShowSummary b/rt/html/Ticket/Elements/ShowSummary
index ffd71d3f9..5a6e7e099 100644
--- a/rt/html/Ticket/Elements/ShowSummary
+++ b/rt/html/Ticket/Elements/ShowSummary
@@ -2,7 +2,7 @@
%#
%# COPYRIGHT:
%#
-%# This software is Copyright (c) 1996-2007 Best Practical Solutions, LLC
+%# This software is Copyright (c) 1996-2005 Best Practical Solutions, LLC
%# <jesse@bestpractical.com>
%#
%# (Except where explicitly superseded by other copyright notices)
@@ -22,9 +22,7 @@
%#
%# 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/copyleft/gpl.html.
+%# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
%#
%#
%# CONTRIBUTION SUBMISSION POLICY:
@@ -45,65 +43,67 @@
%# those contributions and any derivatives thereof.
%#
%# END BPS TAGGED BLOCK }}}
- <table width="100%" class="ticket-summary">
- <tr>
- <td valign="top" width="50%" class="boxcontainer">
- <&| /Widgets/TitleBox, title => loc('The Basics'),
+ <TABLE WIDTH="100%" class="ticketsummary" >
+ <TR>
+ <TD VALIGN=TOP WIDTH="50%" class="boxcontainer">
+ <& /Elements/TitleBoxStart, title => loc('The Basics'),
title_href =>"$RT::WebPath/Ticket/Modify.html?id=".$Ticket->Id,
- class => 'ticket-info-basics' &>
+ title_class=> 'inverse',
+ color => "#993333" &>
<& /Ticket/Elements/ShowBasics, Ticket => $Ticket &>
- </&>
-
+ <& /Elements/TitleBoxEnd &>
+ <br>
% if ($Ticket->QueueObj->TicketCustomFields->First) {
- <&| /Widgets/TitleBox, title => loc('Custom Fields'),
+ <& /Elements/TitleBoxStart, title => loc('Custom Fields'),
title_href =>"$RT::WebPath/Ticket/Modify.html?id=".$Ticket->Id,
- class => 'ticket-info-cfs' &>
+ title_class=> 'inverse',
+ color => "#993333" &>
<& /Ticket/Elements/ShowCustomFields, Ticket => $Ticket &>
- </&>
+ <& /Elements/TitleBoxEnd &>
+
+<br>
% }
- <&| /Widgets/TitleBox, title => loc('People'),
+ <& /Elements/TitleBoxStart, title => loc('People'),
title_href =>"$RT::WebPath/Ticket/ModifyPeople.html?id=".$Ticket->Id,
- class => 'ticket-info-people' &>
- <& /Ticket/Elements/ShowPeople, Ticket => $Ticket &>
- </&>
+ title_class=> 'inverse',
+ color => "#333399" &>
+ <& /Ticket/Elements/ShowPeople, Ticket => $Ticket &>
+ <& /Elements/TitleBoxEnd &>
+ <br>
- <& /Ticket/Elements/ShowAttachments, Ticket => $Ticket, Attachments => $Attachments &>
- <br />
- <& /Ticket/Elements/ShowRequestor, Ticket => $Ticket &>
+ <& /Elements/TitleBoxStart, title => loc('Customers'),
+ title_href =>"$RT::WebPath/Ticket/ModifyCustomers.html?id=".$Ticket->Id,
+ title_class=> 'inverse',
+ color => "#7f007b" &>
+ <& /Ticket/Elements/ShowCustomers, Ticket => $Ticket &>
+ <& /Elements/TitleBoxEnd &>
+
+ <BR>
+ </TD>
+ <TD VALIGN=TOP WIDTH="50%" class="boxcontainer">
- <& /Elements/Callback, %ARGS, _CallbackName => 'LeftColumn' &>
- </td>
- <td valign="top" width="50%" class="boxcontainer">
- <&|/Widgets/TitleBox, title => loc("Reminders"),
- title_href =>"$RT::WebPath/Ticket/Reminders.html?id=".$Ticket->Id,
- class => 'ticket-info-reminders' &>
- <table>
- <tr>
- <td>
- <form action="<%$RT::WebPath%>/Ticket/Display.html" method="post">
- <& /Ticket/Elements/Reminders, Ticket => $Ticket, ShowCompleted => 0 &>
- <div align="right"><input type="submit" class="button" value="Save" /></div>
- </form>
- </td>
- </tr>
- </table>
- </&>
- <&| /Widgets/TitleBox, title => loc("Dates"),
+ <& /Elements/TitleBoxStart, title => loc("Dates"),
title_href =>"$RT::WebPath/Ticket/ModifyDates.html?id=".$Ticket->Id,
- class => 'ticket-info-dates' &>
+ title_class=> 'inverse',
+ color => "#663366" &>
<& /Ticket/Elements/ShowDates, Ticket => $Ticket &>
- </&>
-
- <&| /Widgets/TitleBox, title => loc('Links'),
+ <& /Elements/TitleBoxEnd &>
+ <BR>
+ <& /Elements/TitleBoxStart, title => loc('Links'),
title_href => "$RT::WebPath/Ticket/ModifyLinks.html?id=".$Ticket->Id,
- class => 'ticket-info-links' &>
+ title_class=> 'inverse',
+ titleright => '', color=> "#336633" &>
<& /Elements/ShowLinks, Ticket => $Ticket &>
- </&>
- <& /Elements/Callback, %ARGS, _CallbackName => 'RightColumn' &>
+ <& /Elements/TitleBoxEnd &>
+ <BR>
+ <& /Ticket/Elements/ShowAttachments, Ticket => $Ticket, Attachments => $Attachments &>
+
+ <& /Ticket/Elements/ShowRequestor, Ticket => $Ticket &>
+
- </td>
- </tr>
- </table>
+ </TD>
+ </TR>
+ </TABLE>
<%ARGS>
$Ticket => undef
$Attachments => undef
diff --git a/rt/html/Ticket/Elements/Tabs b/rt/html/Ticket/Elements/Tabs
index 1eb2aa8cf..46e1d4a27 100644
--- a/rt/html/Ticket/Elements/Tabs
+++ b/rt/html/Ticket/Elements/Tabs
@@ -2,7 +2,7 @@
%#
%# COPYRIGHT:
%#
-%# This software is Copyright (c) 1996-2007 Best Practical Solutions, LLC
+%# This software is Copyright (c) 1996-2005 Best Practical Solutions, LLC
%# <jesse@bestpractical.com>
%#
%# (Except where explicitly superseded by other copyright notices)
@@ -22,9 +22,7 @@
%#
%# 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/copyleft/gpl.html.
+%# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
%#
%#
%# CONTRIBUTION SUBMISSION POLICY:
@@ -121,11 +119,11 @@ my $ticket_page_tabs = {
{ title => loc('People'), path => "Ticket/ModifyPeople.html?id=" . $id, },
_E => { title => loc('Links'),
path => "Ticket/ModifyLinks.html?id=" . $id, },
- _F => { title => loc('Reminders'),
- path => "Ticket/Reminders.html?id=" . $id,
- separator => 1, },
- _X => { title => loc('Jumbo'),
- path => "Ticket/ModifyAll.html?id=" . $id,
+ _Eb=> { title => loc('Customers'),
+ path => "Ticket/ModifyCustomers.html?id=" . $id, },
+ _F => { title => loc('Jumbo'),
+ path => "Ticket/ModifyAll.html?id=" . $id,
+ separator => 1
},
};
@@ -140,102 +138,76 @@ foreach my $tab ( sort keys %{$ticket_page_tabs} ) {
$tabs->{'this'}->{"subtabs"} = $ticket_page_tabs;
$current_tab = "Ticket/Display.html?id=" . $id;
-my %can = (
- ModifyTicket => $Ticket->CurrentUserHasRight('ModifyTicket'),
-);
-if ( $can{'ModifyTicket'} or $Ticket->CurrentUserHasRight('ReplyToTicket') ) {
- $actions->{'F'} = {
- title => loc('Reply'),
- path => "Ticket/Update.html?Action=Respond&id=" . $id,
+
+
+
+if ( $Ticket->CurrentUserHasRight('ModifyTicket')
+ or $Ticket->CurrentUserHasRight('ReplyToTicket') ) {
+ $actions->{'A'} = { title => loc('Reply'),
+ path => "Ticket/Update.html?Action=Respond&id=" . $id,
};
}
-if ( $can{'ModifyTicket'} ) {
+if ( $Ticket->CurrentUserHasRight('ModifyTicket') ) {
if ( $Ticket->Status ne 'resolved' ) {
- $actions->{'G'} = {
+ $actions->{'B'} = {
+
path => "Ticket/Update.html?Action=Comment&DefaultStatus=resolved&id=" . $id,
title => loc('Resolve') };
}
if ( $Ticket->Status ne 'open' ) {
- $actions->{'A'} = { path => "Ticket/Display.html?Status=open&id=" . $id,
+ $actions->{'C'} = { path => "Ticket/Display.html?Status=open&id=" . $id,
title => loc('Open it') };
}
}
if ( $Ticket->CurrentUserHasRight('OwnTicket') ) {
- if ( $Ticket->OwnerObj->Id == $RT::Nobody->id
- and ( $can{'ModifyTicket'} or $Ticket->CurrentUserHasRight('TakeTicket') ) )
- {
- $actions->{'B'} = {
- path => "Ticket/Display.html?Action=Take&id=" . $id,
- title => loc('Take'),
- };
+ if ( $Ticket->OwnerObj->id == $RT::Nobody->id ) {
+ $actions->{'D'} = { path => "Ticket/Display.html?Action=Take&id=" . $id,
+ title => loc('Take') };
}
- elsif ( $Ticket->OwnerObj->id != $session{CurrentUser}->id
- and ( $can{'ModifyTicket'} or $Ticket->CurrentUserHasRight('StealTicket') ) )
- {
- $actions->{'C'} = {
- path => "Ticket/Display.html?Action=Steal&id=" . $id,
- title => loc('Steal'),
- };
+ elsif ( $Ticket->OwnerObj->id != $session{CurrentUser}->id ) {
+ $actions->{'E'} = {path => "Ticket/Display.html?Action=Steal&id=" . $id,
+ title => loc('Steal') };
}
}
-if ( $can{'ModifyTicket'} or $Ticket->CurrentUserHasRight('CommentOnTicket') ) {
- $actions->{'E'} = {
- title => loc('Comment'),
- path => "Ticket/Update.html?Action=Comment&id=" . $id,
+if ( $Ticket->CurrentUserHasRight('ModifyTicket')
+ or $Ticket->CurrentUserHasRight('CommentOnTicket') ) {
+ $actions->{'F'} = { title => loc('Comment'),
+ path => "Ticket/Update.html?Action=Comment&id=" . $id,
};
}
}
-if ( (defined $actions->{A} || defined $actions->{B} || defined $actions->{C})
- && (defined $actions->{E} || defined $actions->{F} || defined $actions->{G}) ) {
-
- if (defined $actions->{C}) { $actions->{C}->{separator} = 1 }
- elsif (defined $actions->{B}) { $actions->{B}->{separator} = 1 }
- elsif (defined $actions->{A}) { $actions->{A}->{separator} = 1 }
-}
-
-my $args;
-$args= "?" . $m->comp(
+my $args = "?" . $m->comp(
'/Elements/QueryString',
Query => $ARGS{'Query'} || $session{'CurrentSearchHash'}->{'Query'},
Format => $ARGS{'Format'} || $session{'CurrentSearchHash'}->{'Format'},
OrderBy => $ARGS{'OrderBy'} || $session{'CurrentSearchHash'}->{'OrderBy'},
Order => $ARGS{'Order'} || $session{'CurrentSearchHash'}->{'Order'},
- Page => $ARGS{'Page'} || $session{'CurrentSearchHash'}->{'Page'},
Rows => $ARGS{'Rows'},
) if ($ARGS{'Query'} or $session{'CurrentSearchHash'}->{'Query'});
$args ||= '';
$tabs->{"f"} = { path => "Search/Build.html?NewQuery=1",
- title => loc('New Search')};
+ title => loc('New Query')};
$tabs->{"g"} = { path => "Search/Build.html$args",
- title => loc('Edit Search')};
+ title => loc('Query Builder')};
$tabs->{"h"} = { path => "Search/Edit.html$args",
title => loc('Advanced'),
separator => 1 };
-if ($args) {
+if (defined $session{'tickets'} and $session{'tickets'}->Count) {
$tabs->{"i"} = { path => "Search/Results.html$args",
title => loc('Show Results'),
- };
+ separator => 1,
+ subtabs => $searchtabs };
if ($current_tab =~ "Search/Results.html") {
$current_tab = "Search/Results.html$args";
}
- $tabs->{"j"} = { path => "Search/Bulk.html$args",
- title => loc('Bulk Update'),
- };
- if ($current_tab =~ "Search/Bulk.html") {
- $current_tab = "Search/Bulk.html$args";
- }
- foreach my $searchtab (keys %{$searchtabs}) {
- ($searchtab =~ /^_/) ? $tabs->{"s".$searchtab} = $searchtabs->{$searchtab} : $tabs->{"z_".$searchtab} = $searchtabs->{$searchtab};
- }
}
-
</%INIT>
diff --git a/rt/html/Ticket/ModifyCustomers.html b/rt/html/Ticket/ModifyCustomers.html
new file mode 100644
index 000000000..72d103b23
--- /dev/null
+++ b/rt/html/Ticket/ModifyCustomers.html
@@ -0,0 +1,49 @@
+%# Copyright (c) 2004 Ivan Kohler <ivan-rt@420.am>
+%#
+%# 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.
+<& /Elements/Header, Title => loc("Customers for ticket #[_1]", $Ticket->Id) &>
+<& /Ticket/Elements/Tabs,
+ Ticket => $Ticket,
+ current_tab => "Ticket/ModifyCustomers.html?id=".$Ticket->Id,
+ Title => loc("Customers for ticket #[_1]", $Ticket->Id) &>
+
+<& /Elements/ListActions, actions => \@results &>
+
+<form action="ModifyCustomers.html" method="post">
+<input type="hidden" name="id" value="<%$Ticket->id%>">
+
+<& /Elements/TitleBoxStart, title => loc('Edit Customer Links'), color => "#7f007b"&>
+<& Elements/EditCustomers, Ticket => $Ticket, CustomerString => $CustomerString, ServiceString => $ServiceString &>
+<& /Elements/TitleBoxEnd &>
+<& /Elements/Submit, color => "#7f007b", Label => loc('Save Changes') &>
+</form>
+
+
+<%INIT>
+
+my @results = ();
+my $Ticket = LoadTicket($id);
+
+# if we're trying to search for customers/services and nothing else
+unless ( $OnlySearchForCustomers || $OnlySearchForServices) {
+ @results = ProcessTicketCustomers( TicketObj => $Ticket, ARGSRef => \%ARGS);
+}
+
+</%INIT>
+
+
+<%ARGS>
+$OnlySearchForCustomers => undef
+$OnlySearchForServices => undef
+$CustomerString => undef
+$ServiceString => undef
+$id => undef
+</%ARGS>