summaryrefslogtreecommitdiff
path: root/rt/share
diff options
context:
space:
mode:
authorivan <ivan>2010-05-18 18:49:59 +0000
committerivan <ivan>2010-05-18 18:49:59 +0000
commit624b2d44625f69d71175c3348cae635d580c890b (patch)
treeed57a90db2ecbc72cea6c1d3c175c1dcd1938ab4 /rt/share
parent7f4aff45cd6ef2f630d538294fa9d9c4db4ac4aa (diff)
parente70abd21bab68b23488f7ef1ee2e693a3b365691 (diff)
This commit was generated by cvs2svn to compensate for changes in r9232,
which included commits to RCS files with non-trunk default branches.
Diffstat (limited to 'rt/share')
-rw-r--r--rt/share/fonts/Droid.README5
-rwxr-xr-xrt/share/fonts/DroidSans.ttfbin0 -> 149076 bytes
-rwxr-xr-xrt/share/fonts/DroidSansFallback.ttfbin0 -> 3022632 bytes
-rw-r--r--rt/share/html/Admin/CustomFields/Objects.html152
-rw-r--r--rt/share/html/Admin/CustomFields/index.html58
-rwxr-xr-xrt/share/html/Admin/Elements/EditCustomFields213
-rwxr-xr-xrt/share/html/Admin/Elements/EditScrip1
-rwxr-xr-xrt/share/html/Admin/Elements/EditScrips5
-rwxr-xr-xrt/share/html/Admin/Elements/EditTemplates5
-rwxr-xr-xrt/share/html/Admin/Groups/index.html5
-rwxr-xr-xrt/share/html/Admin/Queues/Modify.html7
-rwxr-xr-xrt/share/html/Admin/Queues/index.html6
-rw-r--r--rt/share/html/Admin/Tools/Configuration.html180
-rw-r--r--rt/share/html/Admin/Users/Memberships.html4
-rwxr-xr-xrt/share/html/Admin/Users/index.html6
-rw-r--r--rt/share/html/Dashboards/Elements/HiddenSearches3
-rw-r--r--rt/share/html/Dashboards/Render.html7
-rw-r--r--rt/share/html/Download/CustomFieldValue/dhandler5
-rw-r--r--rt/share/html/Elements/CollectionAsTable/Row3
-rw-r--r--rt/share/html/Elements/CollectionList26
-rw-r--r--rt/share/html/Elements/ColumnMap24
-rwxr-xr-xrt/share/html/Elements/CreateTicket7
-rw-r--r--rt/share/html/Elements/EditCustomFieldSelect3
-rwxr-xr-xrt/share/html/Elements/EditLinks24
-rw-r--r--rt/share/html/Elements/EditPassword34
-rw-r--r--rt/share/html/Elements/HeaderJavascript2
-rwxr-xr-xrt/share/html/Elements/Login15
-rw-r--r--rt/share/html/Elements/Logo7
-rwxr-xr-xrt/share/html/Elements/MessageBox2
-rwxr-xr-xrt/share/html/Elements/MyReminders1
-rw-r--r--rt/share/html/Elements/RT__CustomField/ColumnMap178
-rw-r--r--rt/share/html/Elements/RT__Queue/ColumnMap54
-rw-r--r--rt/share/html/Elements/RT__Scrip/ColumnMap4
-rw-r--r--rt/share/html/Elements/RT__Template/ColumnMap11
-rw-r--r--rt/share/html/Elements/RT__Ticket/ColumnMap22
-rwxr-xr-xrt/share/html/Elements/SelectQueue3
-rw-r--r--rt/share/html/Elements/ShowCustomFields11
-rwxr-xr-xrt/share/html/Elements/ShowLinks22
-rw-r--r--rt/share/html/Elements/ShowRelationLabel62
-rw-r--r--rt/share/html/Elements/ShowUser24
-rw-r--r--rt/share/html/Elements/ShowUserConcise16
-rw-r--r--rt/share/html/Helpers/CalPopup.html12
-rwxr-xr-xrt/share/html/NoAuth/Logout.html12
-rw-r--r--rt/share/html/NoAuth/css/3.4-compat/misc.css3
-rw-r--r--rt/share/html/NoAuth/css/3.4-compat/titlebox.css4
-rwxr-xr-xrt/share/html/NoAuth/css/3.5-default/misc.css31
-rw-r--r--rt/share/html/NoAuth/css/3.5-default/titlebox.css4
-rw-r--r--rt/share/html/NoAuth/css/autohandler3
-rw-r--r--rt/share/html/NoAuth/css/base/misc.css49
-rw-r--r--rt/share/html/NoAuth/css/print.css11
-rw-r--r--rt/share/html/NoAuth/css/web2/base.css7
-rw-r--r--rt/share/html/NoAuth/css/web2/boxes.css8
-rw-r--r--rt/share/html/NoAuth/css/web2/collection.css52
-rw-r--r--rt/share/html/NoAuth/css/web2/main.css1
-rw-r--r--rt/share/html/NoAuth/css/web2/misc.css27
-rw-r--r--rt/share/html/NoAuth/css/web2/msie.css7
-rw-r--r--rt/share/html/NoAuth/css/web2/portlets.css6
-rw-r--r--rt/share/html/NoAuth/images/autohandler3
-rw-r--r--rt/share/html/NoAuth/js/autohandler3
-rw-r--r--rt/share/html/NoAuth/rss/dhandler48
-rwxr-xr-xrt/share/html/Search/Bulk.html4
-rw-r--r--rt/share/html/Search/Chart136
-rw-r--r--rt/share/html/Search/Elements/Chart34
-rw-r--r--rt/share/html/Search/Elements/ResultsRSSView143
-rwxr-xr-xrt/share/html/Search/Results.html11
-rw-r--r--rt/share/html/Search/Results.rdf57
-rw-r--r--rt/share/html/Search/Results.tsv2
-rwxr-xr-xrt/share/html/SelfService/Error.html2
-rwxr-xr-xrt/share/html/SelfService/Prefs.html34
-rwxr-xr-xrt/share/html/Ticket/Attachment/dhandler7
-rwxr-xr-xrt/share/html/Ticket/Create.html18
-rwxr-xr-xrt/share/html/Ticket/Elements/EditCustomFields2
-rwxr-xr-xrt/share/html/Ticket/Elements/EditDates1
-rw-r--r--rt/share/html/Ticket/Elements/EditTransactionCustomFields2
-rwxr-xr-xrt/share/html/Ticket/Elements/PreviewScrips6
-rwxr-xr-xrt/share/html/Ticket/Elements/ShowAttachments17
-rwxr-xr-xrt/share/html/Ticket/Elements/ShowDates1
-rw-r--r--rt/share/html/Ticket/Elements/ShowGroupMembers4
-rwxr-xr-xrt/share/html/Ticket/Elements/ShowMessageStanza3
-rwxr-xr-xrt/share/html/Ticket/Elements/ShowPeople4
-rwxr-xr-xrt/share/html/Ticket/Elements/ShowTransaction2
-rw-r--r--rt/share/html/Ticket/Elements/UpdateCc26
-rwxr-xr-xrt/share/html/Ticket/ModifyAll.html10
-rwxr-xr-xrt/share/html/Ticket/ModifyDates.html1
-rwxr-xr-xrt/share/html/Ticket/Update.html28
-rw-r--r--rt/share/html/Tools/Reports/CreatedByDates.html8
-rw-r--r--rt/share/html/Tools/Reports/ResolvedByDates.html8
-rwxr-xr-xrt/share/html/User/Elements/Tabs66
-rw-r--r--rt/share/html/Widgets/Form/Select5
89 files changed, 1448 insertions, 702 deletions
diff --git a/rt/share/fonts/Droid.README b/rt/share/fonts/Droid.README
new file mode 100644
index 000000000..3a9cfcaf8
--- /dev/null
+++ b/rt/share/fonts/Droid.README
@@ -0,0 +1,5 @@
+Droid is a font family created by Ascender Corporation for use by the Open Handset Alliance platform Android and licensed under the Apache license. The fonts are intended for use on the small screens of mobile handsets and were designed by Steve Matteson of Ascender Corporation. The name was derived from the Open Handset Alliance platform name Android.
+
+Droid Sans Fallback is a font with CJK support.
+
+See Also: http://en.wikipedia.org/wiki/Droid_(font)
diff --git a/rt/share/fonts/DroidSans.ttf b/rt/share/fonts/DroidSans.ttf
new file mode 100755
index 000000000..458ba59d8
--- /dev/null
+++ b/rt/share/fonts/DroidSans.ttf
Binary files differ
diff --git a/rt/share/fonts/DroidSansFallback.ttf b/rt/share/fonts/DroidSansFallback.ttf
new file mode 100755
index 000000000..38b5b1a53
--- /dev/null
+++ b/rt/share/fonts/DroidSansFallback.ttf
Binary files differ
diff --git a/rt/share/html/Admin/CustomFields/Objects.html b/rt/share/html/Admin/CustomFields/Objects.html
index 20d79b294..06e3739b2 100644
--- a/rt/share/html/Admin/CustomFields/Objects.html
+++ b/rt/share/html/Admin/CustomFields/Objects.html
@@ -56,94 +56,104 @@
<form action="Objects.html" method="post">
<input type="hidden" class="hidden" name="id" value="<% $id %>" />
-<input type="hidden" class="hidden" name="UpdateObjs" value="1" />
+
+% if ( $is_global ) {
+<h2><&|/l&>Applies to all objects</&></h2>
+<input type="checkbox" name="RemoveCustomField-<% $CF->id %>" value="0" />
+<&|/l&>check this box to remove this Custom Field from all objects and be able to choose specific objects.</&>
+% } else {
+<h2><&|/l&>Apply globally</&></h2>
+
+<input type="checkbox" name="AddCustomField-<% $CF->id %>" value="0" />
+<&|/l&>check this box to apply this Custom Field to all objects.</&>
<h2><&|/l&>Selected objects</&></h2>
-<& /Admin/Elements/PickObjects, Objects => \@AssignedObjs, id => $id, Checked => 1 &>
-<h2><&|/l&>Unselected objects</&></h2>
-<& /Admin/Elements/PickObjects, Objects => \@UnassignedObjs, id => $id &>
+<& /Elements/CollectionList,
+ OrderBy => 'id',
+ Order => 'ASC',
+ %ARGS,
+ Collection => $applied,
+ Rows => 0,
+ Page => 1,
+ Format => $format,
+ DisplayFormat => "'__CheckBox.{RemoveCustomField-". $CF->id ."}__',". $format,
+ AllowSorting => 0,
+ ShowEmpty => 0,
+ PassArguments => [
+ qw(id Format Rows Page Order OrderBy),
+ ],
+&>
-<& /Elements/Submit, CheckAll => 1, ClearAll => 1 &>
+<h2><&|/l&>Unselected objects</&></h2>
+<& /Elements/CollectionList,
+ OrderBy => 'id',
+ Order => 'ASC',
+ %ARGS,
+ Collection => $not_applied,
+ Rows => 50,
+ Format => $format,
+ DisplayFormat => "'__CheckBox.{AddCustomField-". $CF->id ."}__',". $format,
+ AllowSorting => 1,
+ ShowEmpty => 0,
+ PassArguments => [
+ qw(id Format Rows Page Order OrderBy),
+ ],
+&>
+
+% }
+
+<& /Elements/Submit, Name => 'UpdateObjs' &>
</form>
<%INIT>
my $CF = RT::CustomField->new($session{'CurrentUser'});
$CF->Load($id) or Abort(loc("Could not load CustomField [_1]"), $id);
-my $LookupType = $CF->LookupType || '';
-$LookupType =~ /^([^-]+)/ ||
- Abort(loc("Object of type [_1] cannot take custom fields", $LookupType));
-
-my $Class = $1;
-my $CollectionClass;
-if (UNIVERSAL::can($Class.'Collection', 'new') ) {
-$CollectionClass = $Class.'Collection';
-
-} elsif (UNIVERSAL::can($Class.'es', 'new') ) {
- $CollectionClass = $Class.'es';
-} elsif (UNIVERSAL::can($Class.'s', 'new') ) {
- $CollectionClass = $Class.'s';
-
-} else {
- Abort(loc("Can't find a collection class for '[_1]'", $Class));
-}
-
-
-my $title = loc('Modify associated objects for [_1]', $CF->Name);
+my $class = $CF->RecordClassFromLookupType;
+Abort(loc("Something wrong. Contact system administrator"))
+ unless $class;
-my $Objects = $CollectionClass->new($session{'CurrentUser'});
+my (@results);
-# If CF is a Group CF, only display user-defined groups
-if ($Class eq 'RT::Group') {
- $Objects->LimitToUserDefinedGroups;
+if ( $UpdateObjs ) {
+ if ( defined (my $del = $ARGS{'RemoveCustomField-'.$CF->id}) ) {
+ foreach my $id ( ref $del? (@$del) : ($del) ) {
+ my $object = $class->new( $session{'CurrentUser'} );
+ if ( $id ) {
+ $object->Load( $id );
+ next unless $object->id;
+ }
+
+ my ($status, $msg) = $CF->RemoveFromObject( $object );
+ push @results, $msg;
+ }
+ }
+ if ( defined (my $add = $ARGS{'AddCustomField-'.$CF->id}) ) {
+ foreach my $id ( ref $add? (@$add) : ($add) ) {
+ my $object = $class->new( $session{'CurrentUser'} );
+ if ( $id ) {
+ $object->Load( $id );
+ next unless $object->id;
+ }
+
+ my ($status, $msg) = $CF->AddToObject( $object );
+ push @results, $msg;
+ }
+ }
}
-my (@results);
-my (@AssignedObjs, @UnassignedObjs);
-
-$Objects->UnLimit;
-$Objects->OrderBy( FIELD => 'Name' );
+my $is_global = $CF->IsApplied(0);
+my $applied = $CF->AppliedTo;
+my $not_applied = $CF->NotAppliedTo;
-my $ObjectCFs;
-$ObjectCFs = RT::ObjectCustomFields->new($session{'CurrentUser'});
-$ObjectCFs->UnLimit;
-$ObjectCFs->LimitToCustomField($id);
+my $collection_class = ref($applied);
+$collection_class =~ s/^RT:://;
-my %seen;
-while (my $OCF = $ObjectCFs->Next) {
- $seen{$OCF->ObjectId}++;
-}
+my $format = RT->Config->Get('AdminSearchResultFormat')->{$collection_class}
+ || '__id__,__Name__';
-while (my $obj = $Objects->Next) {
- my $obj_id = $obj->Id;
-
- if ($UpdateObjs) {
- # Go through and delete all the custom field relationships that this object
- # no longer has
- my $key = "Object-$obj_id-CF-$id";
- if ($ARGS{$key}) {
- if (!$seen{$obj_id}) {
- my ($val, $msg) = $CF->AddToObject($obj);
- push (@results, $msg);
- push @UnassignedObjs, $obj if !$val;
- }
- }
- else {
- push @UnassignedObjs, $obj;
- if ($seen{$obj_id}) {
- my ($val, $msg) = $CF->RemoveFromObject($obj);
- push (@results, $msg);
- pop @UnassignedObjs if !$val;
- }
- }
- }
- elsif (!$seen{$obj_id}) {
- push @UnassignedObjs, $obj;
- }
- next if @UnassignedObjs and $UnassignedObjs[-1] == $obj;
- push @AssignedObjs, $obj;
-}
+my $title = loc('Modify associated objects for [_1]', $CF->Name);
</%INIT>
<%ARGS>
diff --git a/rt/share/html/Admin/CustomFields/index.html b/rt/share/html/Admin/CustomFields/index.html
index 139b8ebd6..16fb593f6 100644
--- a/rt/share/html/Admin/CustomFields/index.html
+++ b/rt/share/html/Admin/CustomFields/index.html
@@ -45,40 +45,38 @@
%# those contributions and any derivatives thereof.
%#
%# END BPS TAGGED BLOCK }}}
-<& /Admin/Elements/Header, Title => loc('Select a Custom Field') &>
+<& /Admin/Elements/Header, Title => $title &>
<& /Admin/Elements/CustomFieldTabs,
current_tab => 'Admin/CustomFields/',
- Title => loc('Select a Custom Field') &>
+ Title => $title,
+&>
-% my @types;
-% my $prev_lookup = '';
-% while (my $CustomFieldObj = $CustomFields->Next) {
-% next unless $CustomFieldObj->CurrentUserHasRight('AdminCustomField');
-% my $lookup = $CustomFieldObj->FriendlyLookupType;
-% if ($lookup ne $prev_lookup) {
-% if ($prev_lookup) {
-</ul>
-% }
-<h2><% loc("Custom Fields for [_1]", $lookup) %></h2>
-<ul>
-% $prev_lookup = $lookup;
-% push @types, [$lookup, $CustomFieldObj->LookupType];
-% }
-%
-<li>
-<a href="Modify.html?id=<% $CustomFieldObj->id %>"><% $CustomFieldObj->Name %>: <% $CustomFieldObj->Description %></a>
-</li>
-% }
-% if ($prev_lookup) {
-</ul>
+% my $tmp = RT::CustomField->new( $session{'CurrentUser'} );
+% if ( $Type ) {
+<h2><% loc("Custom Fields for [_1]", $tmp->FriendlyLookupType( $Type )) %></h2>
% }
+<& /Elements/CollectionList,
+ OrderBy => 'LookupType|Name',
+ Order => 'ASC|ASC',
+ Rows => 50,
+ %ARGS,
+ Collection => $CustomFields,
+ Format => $Format,
+ DisplayFormat => ($Type? '' : '__FriendlyLookupType__,'). $Format,
+ AllowSorting => 1,
+ PassArguments => [
+ qw(Format Rows Page Order OrderBy),
+ qw(Type ShowDisabled)
+ ],
+&>
+
<form action="<%RT->Config->Get('WebPath')%>/Admin/CustomFields/index.html" method="get">
<&|/l&>Only show custom fields for:</&>
<select name="Type">
<option value="" <% !$Type && 'selected="selected"'%> ><% loc('(any)') %></option>
-% for (@types) {
-<option value="<% $_->[1] %>" <% $_->[1] eq $Type && 'selected="selected"'%> ><% $_->[0] %></option>
+% for my $type ( $tmp->LookupTypes ) {
+<option value="<% $type %>" <% $type eq $Type && 'selected="selected"'%> ><% $tmp->FriendlyLookupType( $type ) %></option>
% }
</select>
<br />
@@ -92,8 +90,12 @@
<%args>
$Type => ''
$ShowDisabled => 0
+
+$Format => undef
</%args>
<%INIT>
+my $title = loc('Select a Custom Field');
+
$Type ||= $ARGS{'type'} || '';
if ( !$Type && $ARGS{'type'} ) {
$Type ||= $ARGS{'type'};
@@ -102,7 +104,9 @@ if ( !$Type && $ARGS{'type'} ) {
my $CustomFields = RT::CustomFields->new($session{'CurrentUser'});
$CustomFields->UnLimit;
-$CustomFields->{'find_disabled_rows'} = 1 if $ShowDisabled;
+$CustomFields->FindAllRows if $ShowDisabled;
$CustomFields->LimitToLookupType( $Type ) if $Type;
-$CustomFields->OrderByCols( { FIELD => 'LookupType' }, { FIELD => 'Name' } );
+
+$Format ||= RT->Config->Get('AdminSearchResultFormat')->{'CustomFields'};
+
</%INIT>
diff --git a/rt/share/html/Admin/Elements/EditCustomFields b/rt/share/html/Admin/Elements/EditCustomFields
index 89c6d0f65..0767e4ae4 100755
--- a/rt/share/html/Admin/Elements/EditCustomFields
+++ b/rt/share/html/Admin/Elements/EditCustomFields
@@ -51,155 +51,126 @@
<input type="hidden" class="hidden" name="id" value="<% $Object->Id || ''%>" />
<input type="hidden" class="hidden" name="ObjectType" value="<% $ObjectType %>" />
<input type="hidden" class="hidden" name="SubType" value="<% $SubType %>" />
-<input type="hidden" class="hidden" name="UpdateCFs" value="1" />
-% if ($Object->Id) {
-<h2><&|/l&>Global Custom Fields</&></h2>
-<& PickCustomFields, CustomFields => \@GlobalCFs, ReadOnly => 1, id => $id, SubType => $SubType &>
-% }
<h2><&|/l&>Selected Custom Fields</&></h2>
-<& PickCustomFields, CustomFields => [$ObjectCFs->CustomFields], id => $id, Checked => 1, SubType => $SubType &>
-<h2><&|/l&>Unselected Custom Fields</&></h2>
-<& PickCustomFields, CustomFields => \@UnassignedCFs, id => $id, SubType => $SubType &>
+<& /Elements/CollectionList,
+ %ARGS,
+ Collection => $applied_cfs,
+ Rows => 0,
+ Page => 1,
+ Format => $format,
+ DisplayFormat =>
+ $id
+ ? ("'__RemoveCheckBox.{$id}__',". $format .", '__MoveCF.{$id}__'")
+ : ("'__CheckBox.{RemoveCustomField}__',". $format .", '__MoveCF.{$id}__'"),
+ AllowSorting => 0,
+ ShowEmpty => 0,
+ PassArguments => [
+ qw(Page Order OrderBy),
+ qw(id ObjectType SubType),
+ ],
+&>
-<& /Elements/Submit, CheckAll => 1, ClearAll => 1 &>
+<h2><&|/l&>Unselected Custom Fields</&></h2>
+<& /Elements/CollectionList,
+ OrderBy => 'Name',
+ Order => 'ASC',
+ %ARGS,
+ Collection => $not_applied_cfs,
+ Rows => 50,
+ Format => $format,
+ DisplayFormat => "'__CheckBox.{AddCustomField}__',". $format,
+ AllowSorting => 1,
+ ShowEmpty => 0,
+ PassArguments => [
+ qw(Page Order OrderBy),
+ qw(id ObjectType SubType),
+ ],
+&>
+
+<& /Elements/Submit, Name => 'UpdateCFs' &>
</form>
<%INIT>
-my $CustomFields = RT::CustomFields->new($session{'CurrentUser'});
-my @results;
-my (@GlobalCFs, @UnassignedCFs);
-
-my $id = $Object->Id;
+my $id = $Object->Id || 0;
if ($id and !$Object->CurrentUserHasRight('AssignCustomFields')) {
$m->out('<p><i>', loc('(No custom fields)'), '</i></p>');
return;
}
+my @results;
+
my $lookup = $ObjectType;
$lookup .= "-$SubType" if $SubType;
-$CustomFields->LimitToLookupType($lookup);
-$CustomFields->OrderBy( FIELD => 'Name' );
-
-
-my ($GlobalCFs, $ObjectCFs);
-$ObjectCFs = RT::ObjectCustomFields->new($session{'CurrentUser'});
-$ObjectCFs->UnLimit;
-$ObjectCFs->LimitToObjectId($id);
-$ObjectCFs->LimitToLookupType($lookup);
-
-# Check sanity of SortOrders
-my %SortOrders;
-$SortOrders{ $_->SortOrder }++
- while ($_ = $ObjectCFs->Next);
-
-# If there are duplicates, run though and squash them
-if (grep $_ > 1, values %SortOrders) {
- my $i = 1;
- while ( my $ObjectCF = $ObjectCFs->Next ) {
- $ObjectCF->SetSortOrder( $i++ );
+## deal with moving sortorder of custom fields
+if ( $MoveCustomFieldUp ) { {
+ my $record = RT::ObjectCustomField->new( $session{'CurrentUser'} );
+ $record->LoadByCols( ObjectId => $id, CustomField => $MoveCustomFieldUp );
+ unless ( $record->id ) {
+ push @results, loc("Custom field #[_1] is not applied to this object", $MoveCustomFieldUp);
+ last;
}
- $ObjectCFs->GotoFirstItem;
-}
-
-# {{{ deal with moving sortorder of custom fields
-if ($CustomField and $Move) {
- my $SourceObj = RT::ObjectCustomField->new($session{'CurrentUser'});
- $SourceObj->LoadByCols( ObjectId => $id, CustomField => $CustomField );
-
- my $TargetObj;
- my $target_order = $SourceObj->SortOrder + $Move;
- while (my $ObjectCF = $ObjectCFs->Next) {
- my $this_order = $ObjectCF->SortOrder;
-
- # if we have an exact match, finish the loop now
- ($TargetObj = $ObjectCF, last) if $this_order == $target_order;
-
- # otherwise, we need to apropos toward the general direction
- # ... first, check the sign is correct
- next unless ($this_order - $SourceObj->SortOrder) * $Move > 0;
- # ... next, see if we already have a candidate
- if ($TargetObj) {
- # ... if yes, compare the delta and choose the smaller one
- my $orig_delta = abs($TargetObj->SortOrder - $target_order);
- my $this_delta = abs($this_order - $target_order);
- next if $orig_delta < $this_delta;
- }
-
- $TargetObj = $ObjectCF;
+ my ($status, $msg) = $record->MoveUp;
+ push @results, $msg;
+} }
+if ( $MoveCustomFieldDown ) { {
+ my $record = RT::ObjectCustomField->new( $session{'CurrentUser'} );
+ $record->LoadByCols( ObjectId => $id, CustomField => $MoveCustomFieldDown );
+ unless ( $record->id ) {
+ push @results, loc("Custom field #[_1] is not applied to this object", $MoveCustomFieldDown);
+ last;
}
- if ($TargetObj) {
- # swap their sort order
- my ($s, $t) = ($SourceObj->SortOrder, $TargetObj->SortOrder);
- $TargetObj->SetSortOrder($s);
- $SourceObj->SetSortOrder($t);
- # because order changed, we must redo search for subsequent uses
+ my ($status, $msg) = $record->MoveDown;
+ push @results, $msg;
+} }
+
+if ( $UpdateCFs ) {
+ foreach my $cf_id ( @AddCustomField ) {
+ my $CF = RT::CustomField->new( $session{'CurrentUser'} );
+ $CF->Load( $cf_id );
+ unless ( $CF->id ) {
+ push @results, loc("Couldn't load CustomField #[_1]", $cf_id);
+ next;
+ }
+ my ($status, $msg) = $CF->AddToObject( $Object );
+ push @results, $msg;
+ }
+ foreach my $cf_id ( @RemoveCustomField ) {
+ my $CF = RT::CustomField->new( $session{'CurrentUser'} );
+ $CF->Load( $cf_id );
+ unless ( $CF->id ) {
+ push @results, loc("Couldn't load CustomField #[_1]", $cf_id);
+ next;
+ }
+ my ($status, $msg) = $CF->RemoveFromObject( $Object );
+ push @results, $msg;
}
-
- $ObjectCFs->GotoFirstItem;
-}
-# }}}
-
-if ($id) {
- $GlobalCFs = RT::ObjectCustomFields->new($session{'CurrentUser'});
- $GlobalCFs->LimitToObjectId(0);
- $GlobalCFs->LimitToLookupType($lookup);
}
-while (my $cf = $CustomFields->Next) {
- my $cf_id = $cf->Id;
+my $applied_cfs = RT::CustomFields->new( $session{'CurrentUser'} );
+$applied_cfs->LimitToLookupType($lookup);
+$applied_cfs->LimitToGlobalOrObjectId($id);
+$applied_cfs->ApplySortOrder;
- if ($GlobalCFs and $GlobalCFs->HasEntryForCustomField($cf_id)) {
- push @GlobalCFs, $cf;
- next;
- }
+my $not_applied_cfs = RT::CustomFields->new( $session{'CurrentUser'} );
+$not_applied_cfs->LimitToLookupType($lookup);
+$not_applied_cfs->LimitToNotApplied( $id ? ($id, 0) : (0) );
- if ($UpdateCFs) {
- # Go through and delete all the custom field relationships that this object
- # no longer has
- my $key = "Object-$id-CF-$cf_id";
- if ($ARGS{$key}) {
- if (!$ObjectCFs->HasEntryForCustomField($cf_id)) {
- my ($val, $msg) = $cf->AddToObject($Object);
- push (@results, $msg);
- push @UnassignedCFs, $cf if !$val;
- }
- }
- else {
- push @UnassignedCFs, $cf;
- if ($ObjectCFs->HasEntryForCustomField($cf_id)) {
- my ($val, $msg) = $cf->RemoveFromObject($Object);
- push (@results, $msg);
- pop @UnassignedCFs if !$val;
- }
- }
- }
- elsif (!$ObjectCFs->HasEntryForCustomField($cf_id)) {
- push @UnassignedCFs, $cf;
- }
- else {
- }
-}
-
-# redo search...
-$ObjectCFs = RT::ObjectCustomFields->new($session{'CurrentUser'});
-$ObjectCFs->UnLimit;
-$ObjectCFs->LimitToObjectId($id);
-$ObjectCFs->LimitToLookupType($lookup);
+my $format = RT->Config->Get('AdminSearchResultFormat')->{'CustomFields'};
</%INIT>
<%ARGS>
-$title => undef
-$Move => undef
-$Source => undef
-$CustomField => undef
-$FindDisabledCustomFields => undef
-$UpdateCFs => 0
$Object
$ObjectType
$SubType => ''
+
+$UpdateCFs => undef
+@RemoveCustomField => ()
+@AddCustomField => ()
+$MoveCustomFieldUp => undef
+$MoveCustomFieldDown => undef
</%ARGS>
diff --git a/rt/share/html/Admin/Elements/EditScrip b/rt/share/html/Admin/Elements/EditScrip
index 29ec71cd7..2bcf64d49 100755
--- a/rt/share/html/Admin/Elements/EditScrip
+++ b/rt/share/html/Admin/Elements/EditScrip
@@ -56,6 +56,7 @@
<tr><td align="right"><&|/l&>Description</&>:</td><td>
<input name="Scrip-<% $id %>-Description"
+ size="60"
value="<% $ARGS{"Scrip-$id-Description"} || $scrip->Description || '' %>" />
</td></tr>
diff --git a/rt/share/html/Admin/Elements/EditScrips b/rt/share/html/Admin/Elements/EditScrips
index df349e1b9..dce0390fd 100755
--- a/rt/share/html/Admin/Elements/EditScrips
+++ b/rt/share/html/Admin/Elements/EditScrips
@@ -109,10 +109,7 @@ foreach my $id ( grep $_, @DeleteScrip, map /^DeleteScrip-(\d+)/, keys %ARGS ) {
}
# }}}
-my $dir_path = $m->request_comp->dir_path;
-$Format ||= qq{'<a href="__WebPath__$dir_path/Scrip.html?id=__id__&Queue=$id">__id__</a>/TITLE:#'}
- .qq{,'<a href="__WebPath__$dir_path/Scrip.html?id=__id__&Queue=$id">__Description__</a>/TITLE:Description'}
- .q{,__Stage__, __Condition__, __Action__, __Template__};
+$Format ||= RT->Config->Get('AdminSearchResultFormat')->{'Scrips'};
</%init>
diff --git a/rt/share/html/Admin/Elements/EditTemplates b/rt/share/html/Admin/Elements/EditTemplates
index 0bd68c2c0..7d7d930ce 100755
--- a/rt/share/html/Admin/Elements/EditTemplates
+++ b/rt/share/html/Admin/Elements/EditTemplates
@@ -73,10 +73,7 @@
</form>
<%INIT>
-my $dir_path = $m->request_comp->dir_path;
-$Format ||= qq{'<a href="__WebPath__$dir_path/Template.html?Queue=$id&Template=__id__">__id__</a>/TITLE:#'}
- .qq{,'<a href="__WebPath__$dir_path/Template.html?Queue=$id&Template=__id__">__Name__</a>/TITLE:Name'}
- .qq{,'__Description__'};
+$Format ||= RT->Config->Get('AdminSearchResultFormat')->{'Templates'};
my $QueueObj = RT::Queue->new( $session{'CurrentUser'} );
$QueueObj->Load( $id ) if $id;
diff --git a/rt/share/html/Admin/Groups/index.html b/rt/share/html/Admin/Groups/index.html
index 078f51bd9..17b760c26 100755
--- a/rt/share/html/Admin/Groups/index.html
+++ b/rt/share/html/Admin/Groups/index.html
@@ -113,10 +113,7 @@ else {
$caption = loc("User-defined groups");
}
-
-$Format ||= q{'<a href="__WebPath__/Admin/Groups/Modify.html?id=__id__">__id__</a>/TITLE:#'}
- .q{,'<a href="__WebPath__/Admin/Groups/Modify.html?id=__id__">__Name__</a>/TITLE:Name'}
- .q{,'__Description__'};
+$Format ||= RT->Config->Get('AdminSearchResultFormat')->{'Groups'};
</%INIT>
<%ARGS>
diff --git a/rt/share/html/Admin/Queues/Modify.html b/rt/share/html/Admin/Queues/Modify.html
index df97a68c7..c6ffe179f 100755
--- a/rt/share/html/Admin/Queues/Modify.html
+++ b/rt/share/html/Admin/Queues/Modify.html
@@ -194,6 +194,13 @@ if ( $QueueObj->Id ) {
);
push @results, @linkresults;
push @results, ProcessObjectCustomFieldUpdates( ARGSRef => \%ARGS, Object => $QueueObj );
+ if ( RT->Config->Get('RTAddressRegexp') ) {
+ foreach my $address ( $QueueObj->CorrespondAddress, $QueueObj->CommentAddress ) {
+ next unless defined $address && length $address;
+ next if RT::EmailParser->IsRTAddress( $address );
+ push @results, loc("RTAddressRegexp option in the config doesn't match [_1]", $address );
+ }
+ }
}
</%INIT>
diff --git a/rt/share/html/Admin/Queues/index.html b/rt/share/html/Admin/Queues/index.html
index 52e7b3bfd..c0131b14f 100755
--- a/rt/share/html/Admin/Queues/index.html
+++ b/rt/share/html/Admin/Queues/index.html
@@ -92,7 +92,7 @@
<%INIT>
my $queues = new RT::Queues($session{'CurrentUser'});
-$queues->{'find_disabled_rows'} = 1 if $FindDisabledQueues;
+$queues->FindAllRows if $FindDisabledQueues;
my ($caption);
if ( defined $QueueString && length $QueueString ) {
@@ -111,9 +111,7 @@ if ( defined $QueueString && length $QueueString ) {
: loc("Enabled Queues");
}
-$Format ||= q{'<a href="__WebPath__/Admin/Queues/Modify.html?id=__id__">__id__</a>/TITLE:#'}
- .q{,'<a href="__WebPath__/Admin/Queues/Modify.html?id=__id__">__Name__</a>/TITLE:Name'}
- .q{,__Description__,__Address__,__Priority__,__DefaultDueIn__,__Disabled__};
+$Format ||= RT->Config->Get('AdminSearchResultFormat')->{'Queues'};
</%INIT>
<%ARGS>
diff --git a/rt/share/html/Admin/Tools/Configuration.html b/rt/share/html/Admin/Tools/Configuration.html
index eb48af19c..22c846aca 100644
--- a/rt/share/html/Admin/Tools/Configuration.html
+++ b/rt/share/html/Admin/Tools/Configuration.html
@@ -50,9 +50,7 @@ require Module::Versions::Report;
my $title = loc('System Configuration');
unless ($session{'CurrentUser'}->HasRight( Object=> $RT::System, Right => 'SuperUser')) {
Abort(loc('This feature is only available to system administrators'));
-}
-
-
+}
</%init>
<& /Admin/Elements/Header, Title => $title &>
<& /Admin/Elements/ToolTabs,
@@ -60,18 +58,15 @@ unless ($session{'CurrentUser'}->HasRight( Object=> $RT::System, Right => 'Super
current_subtab => 'Admin/Tools/Configuration.html',
Title => $title &>
-
-
-<h2><&|/l&>Loaded perl modules</&></h2>
-% my $report = Module::Versions::Report::report();
-% my @report = grep /v\d/, split("\n",$report);
-<pre>
-<% join('<br />', @report) |n %>
-</pre>
-
-<h2><&|/l&>RT Config</&></h2>
-<table>
+<&|/Widgets/TitleBox, title => loc("RT Configuration") &>
+<table border="0" cellspacing="0" cellpadding="5" width="100%" class="collection">
+<tr class="collection-as-table">
+<th class="collection-as-table"><&|/l&>Option</&></th>
+<th class="collection-as-table"><&|/l&>Value</&></th>
+<th class="collection-as-table"><&|/l&>Source</&></th>
+</tr>
<%PERL>
+my $index_conf;
foreach my $key ( RT->Config->Options( Overridable => undef, Sorted => 0 ) ) {
my $val = RT->Config->Get( $key );
next unless defined $val;
@@ -90,9 +85,11 @@ foreach my $key ( RT->Config->Options( Overridable => undef, Sorted => 0 ) ) {
else {
$description = loc("core config");
}
+ $index_conf++;
</%PERL>
-<tr><th><% $key %></th>
-<td rowspan="2">\
+<tr class="<% $index_conf%2 ? 'oddline' : 'evenline'%>">
+<td class="collection-as-table"><% $key %></td>
+<td class="collection-as-table">
% if ( $key =~ /Password(?!Length)/i ) {
<em>Password not printed</em>\
% } elsif ( !ref $val ) {
@@ -104,19 +101,38 @@ foreach my $key ( RT->Config->Options( Overridable => undef, Sorted => 0 ) ) {
% } else {
<% ref $val %>\
% }
-</td></tr>
-<tr><td><% $description %></td></tr>
+</td>
+<td class="collection-as-table" style="white-space: nowrap">
+% if ( $description =~ /^.*site config$/ ) {
+<span style="font-weight: bold"><% $description %></span>
+% } else {
+<% $description %>
+% }
+</td>
+</tr>
% }
</table>
-
-<h2><&|/l&>RT Variables</&></h2>
-<table>
-% { no strict qw/refs/;
-% my %config_opt = map { $_ => 1 } RT->Config->Options( Overridable => undef );
-% foreach my $key ( sort keys %{*RT::} ) {
-% next if !${'RT::'.$key} || ref ${'RT::'.$key} || $config_opt{ $key };
-<tr><th>RT::<% $key %></th>
-<td>
+</&>
+<table width="100%">
+ <tr>
+ <td valign="top" width="60%" class="boxcontainer">
+<&|/Widgets/TitleBox, title=> loc("RT core variables") &>
+<table border="0" cellspacing="0" cellpadding="5" width="100%" class="collection">
+<tr class="collection-as-table">
+<th class="collection-as-table"><&|/l&>Variable</&></th>
+<th class="collection-as-table"><&|/l&>Value</&></th>
+</tr>
+<%PERL>
+{ no strict qw/refs/;
+my %config_opt = map { $_ => 1 } RT->Config->Options( Overridable => undef );
+my $index_var;
+foreach my $key ( sort keys %{*RT::} ) {
+ next if !${'RT::'.$key} || ref ${'RT::'.$key} || $config_opt{ $key };
+ $index_var++;
+</%PERL>
+<tr class="collection-as-table <% $index_var%2 ? 'oddline' : 'evenline'%>">
+<td class="collection-as-table">RT::<% $key %></td>
+<td class="collection-as-table">
% if ( $key =~ /Password(?!Length)/i ) {
<em>Password not printed</em>
% } else {
@@ -127,44 +143,100 @@ foreach my $key ( RT->Config->Options( Overridable => undef, Sorted => 0 ) ) {
% }
% }
</table>
+</&>
-<h2><&|/l&>RT Size</&></h2>
-<table>
+<&|/Widgets/TitleBox, title => loc("RT Size") &>
+<table border="0" cellspacing="0" cellpadding="5" width="100%" class="collection">
+<tr class="collection-as-table">
+<th class="collection-as-table"><&|/l&>Object</&></th>
+<th class="collection-as-table"><&|/l&>Size</&></th>
+</tr>
<%PERL>
-for my $type (qw/Ticket Queue Transaction Group/) {
- my $class = 'RT::' . $type . 's';
+my ($index_size, $user_count, $privileged_count);
+for my $type (qw/Tickets Queues Transactions Groups PrivilegedUsers UnprivilegedUsers/) {
+ my $count;
+ my $class = 'RT::' . $type;
+ $class =~ s/Privileged|Unprivileged//;
my $collection = $class->new($RT::SystemUser);
$collection->UnLimit;
- my $count = $collection->CountAll;
+ if ($type =~ /PrivilegedUsers/) {
+ $user_count = $collection->CountAll;
+ $collection->LimitToPrivileged;
+ $count = $privileged_count = $collection->CountAll;
+ } elsif ($type =~ /UnprivilegedUsers/) {
+ $count = $user_count - $privileged_count;
+ } else {
+ $count = $collection->CountAll;
+ }
+ $index_size++;
</%PERL>
-<tr><th><% $type %>s</th>
-<td><% $count %></td></tr>
+<tr class="<% $index_size%2 ? 'oddline' : 'evenline'%>">
+<td class="collection-as-table"><% $type %></td>
+<td class="collection-as-table"><% $count %></td>
+</tr>
% }
+</table>
+</&>
+</td>
+<td valign="top" class="boxcontainer">
-<%PERL>
-my $users = RT::Users->new($RT::SystemUser);
-$users->UnLimit;
-my $user_count = $users->CountAll;
+<&|/Widgets/TitleBox, title => loc("Mason template search order") &>
+<ol>
+% foreach my $path ( map { $_->[1] } $m->interp->comp_root_array ) {
+<li><% $path %></li>
+% }
+</ol>
+</&>
-$users->LimitToPrivileged;
-my $privileged_count = $users->CountAll;
-my $unprivileged_count = $user_count - $privileged_count;
-</%PERL>
-<tr><th>Privileged Users</th>
-<td><% $privileged_count %></td></tr>
-<tr><th>Unprivileged Users</th>
-<td><% $unprivileged_count %></td></tr>
+<&|/Widgets/TitleBox, title => loc("Perl library search order") &>
+<ol>
+% foreach my $inc (@INC) {
+<li><% $inc %></li>
+% }
+</ol>
+</&>
+
+</td>
+</table>
+
+<&|/Widgets/TitleBox, title => loc("Loaded perl modules")&>
+<table border="0" cellspacing="0" cellpadding="5" width="100%" class="collection">
+<tr class="collection-as-table">
+<th class="collection-as-table"><&|/l&>Module</&></th>
+<th class="collection-as-table"><&|/l&>Version</&></th>
+<th class="collection-as-table"><&|/l&>Source</&></th>
+
+
+<%perl>
+my $i = 0;
+my $report = Module::Versions::Report::report();
+my @report = grep /v\d/, split("\n",$report);
+shift @report; # throw away the perl version
+my ($ver, $source, $distfile);
+foreach my $item (@report) {
+if ($item =~ /^\s*(.*?)\s*v(\S+);/) {
+ $item = $1;
+ $ver = $2;
+ $distfile = $item.".pm";
+ $distfile =~ s|::|/|g;
+}
+</%perl>
+<tr class="<% $i++ %2 ? 'oddline' : 'evenline'%>">
+<td class="collection-as-table"><% $item %></td>
+ <td class="collection-as-table">
+ <%$ver%>
+ </td>
+ <td class="collection-as-table">
+ <% $INC{$distfile} %>
+ </td>
+</tr>
+% }
</table>
+</&>
-<h2><&|/l&>Perl configuration</&></h2>
+<&|/Widgets/TitleBox, title => loc("Perl configuration") &>
% require Config;
<pre>
<% Config::myconfig() %>
</pre>
-
-<h2><&|/l&>Perl Include Paths (@INC)</&></h2>
-<pre>
-% foreach my $inc (@INC) {
-<% $inc %>
-% }
-</pre>
+</&>
diff --git a/rt/share/html/Admin/Users/Memberships.html b/rt/share/html/Admin/Users/Memberships.html
index ea5dd258b..cd8574d58 100644
--- a/rt/share/html/Admin/Users/Memberships.html
+++ b/rt/share/html/Admin/Users/Memberships.html
@@ -128,9 +128,7 @@ my $is_not_member = RT::Groups->new( $session{'CurrentUser'} );
$is_not_member->LimitToUserDefinedGroups;
$is_not_member->WithoutMember( PrincipalId => $UserObj->Id );
-$Format ||= q{'<a href="__WebPath__/Admin/Groups/Modify.html?id=__id__">__id__</a>/TITLE:#'}
- .q{,'<a href="__WebPath__/Admin/Groups/Modify.html?id=__id__">__Name__</a>/TITLE:Name'}
- .q{,'__Description__'};
+$Format ||= RT->Config->Get('AdminSearchResultFormat')->{'Groups'};
</%INIT>
<%ARGS>
$id => undef
diff --git a/rt/share/html/Admin/Users/index.html b/rt/share/html/Admin/Users/index.html
index e9a58183d..88a775fc3 100755
--- a/rt/share/html/Admin/Users/index.html
+++ b/rt/share/html/Admin/Users/index.html
@@ -93,7 +93,7 @@
<%INIT>
my $caption;
my $users = RT::Users->new( $session{'CurrentUser'} );
-$users->{'find_disabled_rows'} = 1 if $FindDisabledUsers;
+$users->FindAllRows if $FindDisabledUsers;
if ( defined($UserString) && length $UserString ) {
$caption = loc("Users matching search criteria");
@@ -117,9 +117,7 @@ else {
$users->LimitToPrivileged;
}
-$Format ||= q{'<a href="__WebPath__/Admin/Users/Modify.html?id=__id__">__id__</a>/TITLE:#'}
- .q{,'<a href="__WebPath__/Admin/Users/Modify.html?id=__id__">__Name__</a>/TITLE:Name'}
- .q{,__RealName__, __EmailAddress__};
+$Format ||= RT->Config->Get('AdminSearchResultFormat')->{'Users'};
</%INIT>
<%ARGS>
diff --git a/rt/share/html/Dashboards/Elements/HiddenSearches b/rt/share/html/Dashboards/Elements/HiddenSearches
index aa3a67ebb..753d2fe49 100644
--- a/rt/share/html/Dashboards/Elements/HiddenSearches
+++ b/rt/share/html/Dashboards/Elements/HiddenSearches
@@ -50,6 +50,9 @@
$Dashboard
</%args>
<%init>
+# eliminate deleted searches (id=0) because they confuse this logic
+@searches = grep { $_->Id } @searches;
+
return if @searches == 0;
my @display;
diff --git a/rt/share/html/Dashboards/Render.html b/rt/share/html/Dashboards/Render.html
index 1893b533f..ba01a9d2e 100644
--- a/rt/share/html/Dashboards/Render.html
+++ b/rt/share/html/Dashboards/Render.html
@@ -110,10 +110,11 @@ for my $sub ($session{'CurrentUser'}->UserObj->Attributes->Named('Subscription')
last;
}
-# otherwise honor their search preferences.. otherwise 20 rows
-if (!$rows) {
+# otherwise honor their search preferences.. otherwise 50 rows
+# $rows == 0 means unlimited, which we don't want to ignore from above
+unless (defined($rows)) {
my $prefs = $session{'CurrentUser'}->UserObj->Preferences("SearchDisplay") || {};
- $rows = defined($prefs->{'RowsPerPage'}) ? $prefs->{'RowsPerPage'} : 20;
+ $rows = defined($prefs->{'RowsPerPage'}) ? $prefs->{'RowsPerPage'} : 50;
}
my $title = loc 'Dashboard [_1]', $DashboardObj->Name;
diff --git a/rt/share/html/Download/CustomFieldValue/dhandler b/rt/share/html/Download/CustomFieldValue/dhandler
index 218de33c8..d8c703904 100644
--- a/rt/share/html/Download/CustomFieldValue/dhandler
+++ b/rt/share/html/Download/CustomFieldValue/dhandler
@@ -63,7 +63,10 @@ unless ($OCFV->id) {
my $content_type = $OCFV->ContentType || 'text/plain';
-unless (RT->Config->Get('TrustHTMLAttachments')) {
+if (RT->Config->Get('AlwaysDownloadAttachments')) {
+ $r->headers_out->{'Content-Disposition'} = "attachment; filename=" . $OCFV->Content;
+}
+elsif (!RT->Config->Get('TrustHTMLAttachments')) {
$content_type = 'text/plain' if ($content_type =~ /^text\/html/i);
}
diff --git a/rt/share/html/Elements/CollectionAsTable/Row b/rt/share/html/Elements/CollectionAsTable/Row
index fa7474b6c..a1af9f383 100644
--- a/rt/share/html/Elements/CollectionAsTable/Row
+++ b/rt/share/html/Elements/CollectionAsTable/Row
@@ -54,9 +54,10 @@ $Depth => undef
$Warning => undef
$ColumnMap => {}
$Class => 'RT__Ticket'
+$Classes => ''
</%ARGS>
<%init>
-$m->out( '<tr class="'
+$m->out( '<tr class="' . $Classes . ' '
. ( $Warning ? 'warnline' : $i % 2 ? 'oddline' : 'evenline' ) . '" >'
. "\n" );
use HTML::Entities;
diff --git a/rt/share/html/Elements/CollectionList b/rt/share/html/Elements/CollectionList
index 6f21420f5..c7bdfd903 100644
--- a/rt/share/html/Elements/CollectionList
+++ b/rt/share/html/Elements/CollectionList
@@ -54,7 +54,9 @@ if (!$Collection && $Class eq 'RT::Tickets') {
my $TotalFound = $Collection->CountAll();
return '' if !$TotalFound && !$ShowEmpty;
-if ( @OrderBy ) {
+# XXX: ->{'order_by'} is hacky, but there is no way to check if
+# collection is ordered or not
+if ( @OrderBy && ($AllowSorting || !$Collection->{'order_by'}) ) {
if ( $OrderBy[0] =~ /\|/ ) {
@OrderBy = split /\|/, $OrderBy[0];
@Order = split /\|/,$Order[0];
@@ -122,13 +124,27 @@ my ($i, $column_map) = (0, {});
while ( my $record = $Collection->Next ) {
# Every ten rows, flush the buffer and put something on the page.
$m->flush_buffer unless ++$i % 10;
+
+ my $warning = 0;
+ my $Classes = '';
+
+ $m->callback(
+ CallbackName => 'EachRow',
+ Record => $record,
+ Warning => \$warning,
+ Classes => \$Classes,
+ Format => \@Format,
+ );
+
$m->comp('/Elements/CollectionAsTable/Row',
- i => $i,
- Format => \@Format,
- record => $record,
- maxitems => $maxitems,
+ i => $i,
+ Format => \@Format,
+ record => $record,
+ maxitems => $maxitems,
ColumnMap => $column_map,
Class => $Class,
+ Warning => $warning,
+ Classes => $Classes,
);
}
diff --git a/rt/share/html/Elements/ColumnMap b/rt/share/html/Elements/ColumnMap
index 71517e063..a1475a99d 100644
--- a/rt/share/html/Elements/ColumnMap
+++ b/rt/share/html/Elements/ColumnMap
@@ -92,6 +92,26 @@ my $COLUMN_MAP = {
value => sub { return $_[0]->LastUpdatedByObj->Name }
},
+ CustomField => {
+ attribute => sub { return shift @_ },
+ title => sub { return pop @_ },
+ value => sub {
+ # Display custom field contents, separated by newlines.
+ # For Image custom fields we also show a thumbnail here.
+
+ my $values = $_[0]->CustomFieldValues( $_[-1] );
+ my @values = map {
+ (
+ ($_->CustomFieldObj->Type eq 'Image')
+ ? \($m->scomp( '/Elements/ShowCustomFieldImage', Object => $_ ))
+ : $_->Content
+ ),
+ \'<br />',
+ } @{ $values->ItemsArrayRef };
+ pop @values; # Remove that last <br />
+ return @values;
+ },
+ },
CheckBox => {
title => sub {
@@ -136,8 +156,12 @@ my $COLUMN_MAP = {
$_ => { value => sub { return \$value } };
} qw(WebPath WebBaseURL WebURL)),
+ WebRequestPath => { value => sub { substr( $m->request_path, 1 ) } },
+ WebRequestPathDir => { value => sub { substr( $m->request_comp->dir_path, 1 ) } },
};
+$COLUMN_MAP->{'CF'} = $COLUMN_MAP->{'CustomField'};
+
</%ONCE>
<%INIT>
$m->callback( COLUMN_MAP => $COLUMN_MAP, CallbackName => 'Once', CallbackOnce => 1 );
diff --git a/rt/share/html/Elements/CreateTicket b/rt/share/html/Elements/CreateTicket
index 9c8f3aadf..fd2ba9e53 100755
--- a/rt/share/html/Elements/CreateTicket
+++ b/rt/share/html/Elements/CreateTicket
@@ -45,6 +45,9 @@
%# those contributions and any derivatives thereof.
%#
%# END BPS TAGGED BLOCK }}}
-<form action="<% RT->Config->Get('WebPath') %>/Ticket/Create.html" name="CreateTicketInQueue" id="CreateTicketInQueue">
-<&|/l, $m->scomp('/Elements/SelectNewTicketQueue', OnChange => 'document.CreateTicketInQueue.submit()')&><input type="submit" class="button" value="New ticket in" />&nbsp;[_1]</&>
+<form action="<% RT->Config->Get('WebPath') %><% $SendTo %>" name="CreateTicketInQueue" id="CreateTicketInQueue">
+<&|/l, $m->scomp('/Elements/SelectNewTicketQueue', OnChange => 'document.CreateTicketInQueue.submit()', SendTo => $SendTo ) &><input type="submit" class="button" value="New ticket in" />&nbsp;[_1]</&>
</form>
+<%ARGS>
+$SendTo => '/Ticket/Create.html',
+</%ARGS>
diff --git a/rt/share/html/Elements/EditCustomFieldSelect b/rt/share/html/Elements/EditCustomFieldSelect
index 8fe79f9f9..30b06dbd1 100644
--- a/rt/share/html/Elements/EditCustomFieldSelect
+++ b/rt/share/html/Elements/EditCustomFieldSelect
@@ -52,7 +52,7 @@
% my @category;
% my $id = $NamePrefix . $CustomField->Id;
% my $out = $m->scomp('SELF:options', %ARGS, SelectedRef => \$selected, CategoryRef => \@category);
-% if (@category and not $CustomField->BasedOnObj->id) {
+% if (!$HideCategory and @category and not $CustomField->BasedOnObj->id) {
<script type="text/javascript" src="<%RT->Config->Get('WebPath')%>/NoAuth/js/cascaded.js"></script>
%# XXX - Hide this select from w3m?
<select onchange="filter_cascade('<% $id %>-Values', this.value)" name="<% $id %>-Category" class="CF-<%$CustomField->id%>-Edit">
@@ -108,6 +108,7 @@ $Default => undef
$Values => undef
$Multiple => 0
$Rows => undef
+$HideCategory => 0
</%ARGS>
<%METHOD options>
diff --git a/rt/share/html/Elements/EditLinks b/rt/share/html/Elements/EditLinks
index 637762e1b..90acb4692 100755
--- a/rt/share/html/Elements/EditLinks
+++ b/rt/share/html/Elements/EditLinks
@@ -52,7 +52,7 @@
<table>
<tr>
- <td class="labeltop"><&|/l&>Depends on</&>:</td>
+ <td class="labeltop"><& ShowRelationLabel, id => $id, Label => loc('Depends on'), Relation => 'DependsOn' &>:</td>
<td class="value">
% while (my $link = $Object->DependsOn->Next) {
<input type="checkbox" class="checkbox" name="DeleteLink--<%$link->Type%>-<%$link->Target%>" value="1" />
@@ -61,7 +61,7 @@
</td>
</tr>
<tr>
- <td class="labeltop"><&|/l&>Depended on by</&>:</td>
+ <td class="labeltop"><& ShowRelationLabel, id => $id, Label => loc('Depended on by'), Relation => 'DependedOnBy' &>:</td>
<td class="value">
% while (my $link = $Object->DependedOnBy->Next) {
<input type="checkbox" class="checkbox" name="DeleteLink-<%$link->Base%>-<%$link->Type%>-" value="1" />
@@ -70,7 +70,7 @@
</td>
</tr>
<tr>
- <td class="labeltop"><&|/l&>Parents</&>:</td>
+ <td class="labeltop"><& ShowRelationLabel, id => $id, Label => loc('Parents'), Relation => 'Parents' &>:</td>
<td class="value">
% while (my $link = $Object->MemberOf->Next) {
<input type="checkbox" class="checkbox" name="DeleteLink--<%$link->Type%>-<%$link->Target%>" value="1" />
@@ -79,7 +79,7 @@
</td>
</tr>
<tr>
- <td class="labeltop"><&|/l&>Children</&>:</td>
+ <td class="labeltop"><& ShowRelationLabel, id => $id, Label => loc('Children'), Relation => 'Children' &>:</td>
<td class="value">
% while (my $link = $Object->Members->Next) {
<input type="checkbox" class="checkbox" name="DeleteLink-<%$link->Base%>-<%$link->Type%>-" value="1" />
@@ -88,7 +88,7 @@
</td>
</tr>
<tr>
- <td class="labeltop"><&|/l&>Refers to</&>:</td>
+ <td class="labeltop"><& ShowRelationLabel, id => $id, Label => loc('Refers to'), Relation => 'RefersTo' &>:</td>
<td class="value">
% while (my $link = $Object->RefersTo->Next) {
<input type="checkbox" class="checkbox" name="DeleteLink--<%$link->Type%>-<%$link->Target%>" value="1" />
@@ -97,7 +97,7 @@
</td>
</tr>
<tr>
- <td class="labeltop"><&|/l&>Referred to by</&>:</td>
+ <td class="labeltop"><& ShowRelationLabel, id => $id, Label => loc('Referred to by'), Relation => 'ReferredToBy' &>:</td>
<td class="value">
% while (my $link = $Object->ReferredToBy->Next) {
% # Skip reminders
@@ -134,27 +134,27 @@
</tr>
% }
<tr>
- <td class="label"><&|/l&>Depends on</&>:</td>
+ <td class="label"><& ShowRelationLabel, id => $id, Label => loc('Depends on'), Relation => 'DependsOn' &>:</td>
<td class="entry"><input name="<%$id%>-DependsOn" /></td>
</tr>
<tr>
- <td class="label"><&|/l&>Depended on by</&>:</td>
+ <td class="label"><& ShowRelationLabel, id => $id, Label => loc('Depended on by'), Relation => 'DependedOnBy' &>:</td>
<td class="entry"><input name="DependsOn-<%$id%>" /></td>
</tr>
<tr>
- <td class="label"><&|/l&>Parents</&>:</td>
+ <td class="label"><& ShowRelationLabel, id => $id, Label => loc('Parents'), Relation => 'Parents' &>:</td>
<td class="entry"><input name="<%$id%>-MemberOf" /></td>
</tr>
<tr>
- <td class="label"><&|/l&>Children</&>:</td>
+ <td class="label"><& ShowRelationLabel, id => $id, Label => loc('Children'), Relation => 'Children' &>:</td>
<td class="entry"> <input name="MemberOf-<%$id%>" /></td>
</tr>
<tr>
- <td class="label"><&|/l&>Refers to</&>:</td>
+ <td class="label"><& ShowRelationLabel, id => $id, Label => loc('Refers to'), Relation => 'RefersTo' &>:</td>
<td class="entry"><input name="<%$id%>-RefersTo" /></td>
</tr>
<tr>
- <td class="label"><&|/l&>Referred to by</&>:</td>
+ <td class="label"><& ShowRelationLabel, id => $id, Label => loc('Referred to by'), Relation => 'ReferredToBy' &>:</td>
<td class="entry"> <input name="RefersTo-<%$id%>" /></td>
</tr>
% $m->callback( CallbackName => 'NewLink' );
diff --git a/rt/share/html/Elements/EditPassword b/rt/share/html/Elements/EditPassword
new file mode 100644
index 000000000..3b0ec0b32
--- /dev/null
+++ b/rt/share/html/Elements/EditPassword
@@ -0,0 +1,34 @@
+% unless ( $cond{'CanSet'} ) {
+<% $cond{'Reason'} %><br />
+% } else {
+<table>
+
+% if ( $cond{'RequireCurrent'} ) {
+<tr>
+<td><&|/l&>Your current password</&>:</td>
+<td><input type="password" name="<% $Name[0] %>" size="16" autocomplete="off" /></td>
+</tr>
+% }
+
+<tr>
+<td><&|/l&>New password</&>:</td>
+<td><input type="password" name="<% $Name[1] %>" size="16" autocomplete="off" /></td>
+</tr>
+
+<tr>
+<td><&|/l&>Retype Password</&>:</td>
+<td><input type="password" name="<% $Name[2] %>" size="16" autocomplete="off" /></td>
+</tr>
+
+</table>
+% }
+
+<%ARGS>
+$User
+@Name => qw(CurrentPass NewPass1 NewPass2)
+</%ARGS>
+<%INIT>
+
+my %cond = $User->CurrentUserRequireToSetPassword;
+
+</%INIT>
diff --git a/rt/share/html/Elements/HeaderJavascript b/rt/share/html/Elements/HeaderJavascript
index 6ee88a13b..c4eb17504 100644
--- a/rt/share/html/Elements/HeaderJavascript
+++ b/rt/share/html/Elements/HeaderJavascript
@@ -111,7 +111,7 @@ $onload => undef
typeField.setAttribute('value', 'text/html');
textArea.parentNode.appendChild(typeField);
- var oFCKeditor = new FCKeditor( textArea.name, '100%', <% RT->Config->Get('MessageBoxRichTextHeight') %> );
+ var oFCKeditor = new FCKeditor( textArea.name, '100%', <% RT->Config->Get('MessageBoxRichTextHeight', $session{CurrentUser} ) %> );
oFCKeditor.BasePath = "<%RT->Config->Get('WebPath')%>/NoAuth/RichText/";
oFCKeditor.ReplaceTextarea();
}
diff --git a/rt/share/html/Elements/Login b/rt/share/html/Elements/Login
index 8dfbe51d1..e768b0e7a 100755
--- a/rt/share/html/Elements/Login
+++ b/rt/share/html/Elements/Login
@@ -64,6 +64,21 @@ my $form_action = defined $goto ? $goto
: defined $req_uri ? $req_uri
: RT->Config->Get('WebPath')
;
+
+# sanitize $form_action
+my $uri = URI->new($form_action);
+
+# You get undef scheme with a relative uri like "/Search/Build.html"
+unless (!defined($uri->scheme) || $uri->scheme eq 'http' || $uri->scheme eq 'https') {
+ $form_action = RT->Config->Get('WebPath');
+}
+
+# Make sure we're logging in to the same domain
+# You can get an undef authority with a relative uri like "index.html"
+my $uri_base_url = URI->new(RT->Config->Get('WebBaseURL'));
+unless (!defined($uri->authority) || $uri->authority eq $uri_base_url->authority) {
+ $form_action = RT->Config->Get('WebPath');
+}
</%INIT>
% $m->callback( %ARGS, CallbackName => 'Header' );
diff --git a/rt/share/html/Elements/Logo b/rt/share/html/Elements/Logo
index 359738b5e..e6cb1ad4b 100644
--- a/rt/share/html/Elements/Logo
+++ b/rt/share/html/Elements/Logo
@@ -46,10 +46,11 @@
%#
%# END BPS TAGGED BLOCK }}}
<div id="logo">
-<a href="http://bestpractical.com"><img
+<a href="<%$ARGS{'LogoLinkURL'}||RT->Config->Get('LogoLinkURL')%>"><img
src="<%$ARGS{'LogoURL'}||RT->Config->Get('LogoURL')%>"
- alt="<% loc("Best Practical Solutions, LLC corporate logo") %>"
- width="177" height="33" /></a>
+ alt="<%loc($ARGS{'LogoAltText'}||RT->Config->Get('LogoAltText'))%>"
+ width="<%$ARGS{'LogoImageWidth'}||RT->Config->Get('LogoImageWidth')%>"
+ height="<%$ARGS{'LogoImageHeight'}||RT->Config->Get('LogoImageHeight')%>" /></a>
% if ( $ShowName ) {
<span class="rtname"><% $Name || loc("RT for [_1]", RT->Config->Get('rtname')) %></span>
% }
diff --git a/rt/share/html/Elements/MessageBox b/rt/share/html/Elements/MessageBox
index 4985b23e3..854528c23 100755
--- a/rt/share/html/Elements/MessageBox
+++ b/rt/share/html/Elements/MessageBox
@@ -46,7 +46,7 @@
%#
%# END BPS TAGGED BLOCK }}}
<textarea class="messagebox" cols="<% $Width %>" rows="<% $Height %>" <% $wrap_type |n %> name="<% $Name %>" id="<% $Name %>">\
-% $m->callback( %ARGS );
+% $m->callback( %ARGS, SignatureRef => \$signature );
<% $Default || '' %><% $message %><% $signature %></textarea>
% $m->callback( %ARGS, CallbackName => 'AfterTextArea' );
<%INIT>
diff --git a/rt/share/html/Elements/MyReminders b/rt/share/html/Elements/MyReminders
index 25fdf5d48..53e3f99c7 100755
--- a/rt/share/html/Elements/MyReminders
+++ b/rt/share/html/Elements/MyReminders
@@ -47,6 +47,7 @@
%# END BPS TAGGED BLOCK }}}
%# DEPRECATED
<&|/Widgets/TitleBox,
+ class => 'reminders',
title => loc("Reminders") &>
<table width="100%">
% my $i =0;
diff --git a/rt/share/html/Elements/RT__CustomField/ColumnMap b/rt/share/html/Elements/RT__CustomField/ColumnMap
new file mode 100644
index 000000000..6d8d76a4c
--- /dev/null
+++ b/rt/share/html/Elements/RT__CustomField/ColumnMap
@@ -0,0 +1,178 @@
+%# BEGIN BPS TAGGED BLOCK {{{
+%#
+%# COPYRIGHT:
+%#
+%# This software is Copyright (c) 1996-2009 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., 51 Franklin Street, Fifth Floor, Boston, MA
+%# 02110-1301 or visit their web page on the internet at
+%# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html.
+%#
+%#
+%# CONTRIBUTION SUBMISSION POLICY:
+%#
+%# (The following paragraph is not intended to limit the rights granted
+%# to you to modify and distribute this software under the terms of
+%# the GNU General Public License and is only of importance to you if
+%# you choose to contribute your changes and enhancements to the
+%# community by submitting them to Best Practical Solutions, LLC.)
+%#
+%# By intentionally submitting any modifications, corrections or
+%# derivatives to this work, or any other work intended for use with
+%# Request Tracker, to Best Practical Solutions, LLC, you confirm that
+%# you are the copyright holder for those contributions and you grant
+%# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable,
+%# royalty-free, perpetual, license to use, copy, create derivative
+%# works based on those contributions, and sublicense and distribute
+%# those contributions and any derivatives thereof.
+%#
+%# END BPS TAGGED BLOCK }}}
+<%ARGS>
+$Name => undef
+$Attr => undef
+</%ARGS>
+<%ONCE>
+my $COLUMN_MAP = {
+ id => {
+ title => '#', # loc
+ attribute => 'id',
+ align => 'right',
+ value => sub { return $_[0]->id },
+ },
+ Disabled => {
+ title => \'&nbsp;',
+ attribute => 'Disabled',
+ value => sub { return $_[0]->Disabled? $_[0]->loc('Disabled'): $_[0]->loc('Enabled') },
+ },
+
+ map(
+ { my $c = $_; $c => {
+ title => $c, attribute => $c,
+ value => sub { return $_[0]->$c() },
+ } }
+ qw(Name Description Type LookupType Pattern)
+ ),
+ map(
+ { my $c = $_; my $short = $c; $short =~ s/^Friendly//;
+ $c => {
+ title => $short, attribute => $short,
+ value => sub { return $_[0]->$c() },
+ } }
+ qw(FriendlyLookupType FriendlyType FriendlyPattern)
+ ),
+ MaxValues => {
+ title => 'MaxValues', # loc
+ attribute => 'MaxValues',
+ value => sub {
+ my $v = $_[0]->MaxValues;
+ return !$v ? $_[0]->loc('unlimited') : $v == 0 ? $_[0]->loc('one') : $v;
+ },
+ },
+ AppliedTo => {
+ title => 'Applied', # loc
+ value => sub {
+ if ( $_[0]->IsApplied ) {
+ return $_[0]->loc('Global');
+ }
+
+ my $collection = $_[0]->AppliedTo;
+ return '' unless $collection;
+
+ $collection->RowsPerPage(10);
+
+ my $found = 0;
+ my $res = '';
+ while ( my $record = $collection->Next ) {
+ $res .= ', ' if $res;
+
+ my $id = '';
+ $id = $record->Name if $record->can('Name');
+ $id ||= "#". $record->id;
+ $res .= $id;
+
+ $found++;
+ }
+ $res .= ', ...' if $found >= 10;
+ return $res;
+ },
+
+ },
+ RemoveCheckBox => {
+ title => sub {
+ my $name = 'RemoveCustomField';
+ my $checked = $m->request_args->{ $name .'All' }? 'checked="checked"': '';
+
+ return \qq{<input type="checkbox" name="${name}All" value="1" $checked
+ onclick="setCheckbox(this.form, '$name', this.checked)" />};
+ },
+ value => sub {
+ my $id = $_[0]->id;
+ return '' if $_[0]->IsApplied;
+
+ my $name = 'RemoveCustomField';
+ my $arg = $m->request_args->{ $name };
+
+ my $checked = '';
+ if ( $arg && ref $arg ) {
+ $checked = 'checked="checked"' if grep $_ == $id, @$arg;
+ }
+ elsif ( $arg ) {
+ $checked = 'checked="checked"' if $arg == $id;
+ }
+ return \qq{<input type="checkbox" name="$name" value="$id" $checked />}
+ },
+ },
+ MoveCF => {
+ title => 'Move',
+ value => sub {
+ my $id = $_[0]->id;
+
+ my $context = $_[2] || 0;
+ return '' unless $_[0]->IsApplied( $context );
+
+ my $name = 'MoveCustomField';
+ my $args = $m->caller_args( 1 );
+ my @pass = ref $args->{'PassArguments'}
+ ? @{$args->{'PassArguments'}}
+ : ($args->{'PassArguments'});
+ my %pass = map { $_ => $args->{$_} } grep exists $args->{$_}, @pass;
+
+ my $uri = RT->Config->Get('WebPath') . $m->request_path;
+
+ my @res = (
+ \'<a href="',
+ $uri .'?'. $m->comp("/Elements/QueryString", %pass, MoveCustomFieldUp => $id ),
+ \'">', loc('[Up]'), \'</a>',
+ \' <a href="',
+ $uri .'?'. $m->comp("/Elements/QueryString", %pass, MoveCustomFieldDown => $id ),
+ \'">', loc('[Down]'), \'</a>'
+ );
+
+ return @res;
+ },
+ },
+};
+
+</%ONCE>
+<%INIT>
+$m->callback( COLUMN_MAP => $COLUMN_MAP, CallbackName => 'ColumnMap', CallbackOnce => 1 );
+return GetColumnMapEntry( Map => $COLUMN_MAP, Name => $Name, Attribute => $Attr );
+</%INIT>
diff --git a/rt/share/html/Elements/RT__Queue/ColumnMap b/rt/share/html/Elements/RT__Queue/ColumnMap
index 5c56004d1..f44ab32c3 100644
--- a/rt/share/html/Elements/RT__Queue/ColumnMap
+++ b/rt/share/html/Elements/RT__Queue/ColumnMap
@@ -70,43 +70,33 @@ my $COLUMN_MAP = {
title => 'Address', # loc
value => sub { return ($_[0]->CorrespondAddress||'-') .'/'. ($_[0]->CommentAddress||'-') },
},
- Name => {
- title => 'Name', # loc
- attribute => 'Name',
- value => sub { return $_[0]->Name() },
- },
- Description => {
- title => 'Description', # loc
- attribute => 'Description',
- value => sub { return $_[0]->Description() },
- },
- CorrespondAddress => {
- title => 'CorrespondAddress', # loc
- attribute => 'CorrespondAddress',
- value => sub { return $_[0]->CorrespondAddress() },
- },
- CommentAddress => {
- title => 'CommentAddress', # loc
- attribute => 'CommentAddress',
- value => sub { return $_[0]->CommentAddress() },
- },
- InitialPriority => {
- title => 'InitialPriority', # loc
- attribute => 'InitialPriority',
- value => sub { return $_[0]->InitialPriority() },
+
+ # SubjectTag is special as we can not sort
+ SubjectTag => {
+ title => 'SubjectTag', # loc
+ value => sub { return $_[0]->SubjectTag },
},
- FinalPriority => {
- title => 'FinalPriority', # loc
- attribute => 'FinalPriority',
- value => sub { return $_[0]->FinalPriority() },
+ Sign => {
+ title => 'Sign', # loc
+ value => sub { return $_[0]->Sign? $_[0]->loc('yes') : $_[0]->loc('no') },
},
- DefaultDueIn => {
- title => 'DefaultDueIn', # loc
- attribute => 'DefaultDueIn',
- value => sub { return $_[0]->DefaultDueIn() },
+ Encrypt => {
+ title => 'Encrypt', # loc
+ value => sub { return $_[0]->Encrypt? $_[0]->loc('yes') : $_[0]->loc('no') },
},
};
+foreach my $field (qw(
+ Name Description CorrespondAddress CommentAddress
+ InitialPriority FinalPriority DefaultDueIn
+)) {
+ $COLUMN_MAP->{$field} = {
+ title => $field,
+ attribute => $field,
+ value => sub { return $_[0]->$field() },
+ },
+}
+
</%ONCE>
<%INIT>
$m->callback( COLUMN_MAP => $COLUMN_MAP, CallbackName => 'ColumnMap', CallbackOnce => 1 );
diff --git a/rt/share/html/Elements/RT__Scrip/ColumnMap b/rt/share/html/Elements/RT__Scrip/ColumnMap
index 88b4c4bea..3e1d4074f 100644
--- a/rt/share/html/Elements/RT__Scrip/ColumnMap
+++ b/rt/share/html/Elements/RT__Scrip/ColumnMap
@@ -64,6 +64,10 @@ my $COLUMN_MAP = {
return $_[0]->loc('Global');
},
},
+ QueueId => {
+ title => 'Queue', # loc
+ value => sub { $_[0]->Queue },
+ },
Condition => {
title => 'Condition', # loc
value => sub { return $_[0]->loc( $_[0]->ScripConditionObj->Name ) },
diff --git a/rt/share/html/Elements/RT__Template/ColumnMap b/rt/share/html/Elements/RT__Template/ColumnMap
index 851cc9dec..e7c149575 100644
--- a/rt/share/html/Elements/RT__Template/ColumnMap
+++ b/rt/share/html/Elements/RT__Template/ColumnMap
@@ -67,6 +67,17 @@ my $COLUMN_MAP = {
attribute => 'Description',
value => sub { return $_[0]->Description() },
},
+ Queue => {
+ title => 'Queue', # loc
+ value => sub {
+ return $_[0]->QueueObj->Name if $_[0]->Queue;
+ return $_[0]->loc('Global');
+ },
+ },
+ QueueId => {
+ title => 'Queue', # loc
+ value => sub { $_[0]->Queue },
+ },
};
</%ONCE>
diff --git a/rt/share/html/Elements/RT__Ticket/ColumnMap b/rt/share/html/Elements/RT__Ticket/ColumnMap
index 7df471009..c1f9e319a 100644
--- a/rt/share/html/Elements/RT__Ticket/ColumnMap
+++ b/rt/share/html/Elements/RT__Ticket/ColumnMap
@@ -303,26 +303,6 @@ $COLUMN_MAP = {
value => sub { return \('<input type="checkbox" class="checkbox" name="UpdateTicket'.$_[0]->id.'" value="1" checked="checked" />') }
},
- CustomField => {
- attribute => sub { return shift @_ },
- title => sub { return pop @_ },
- value => sub {
- # Display custom field contents, separated by newlines.
- # For Image custom fields we also show a thumbnail here.
-
- my $values = $_[0]->CustomFieldValues( $_[-1] );
- my @values = map {
- (
- ($_->CustomFieldObj->Type eq 'Image')
- ? \($m->scomp( '/Elements/ShowCustomFieldImage', Object => $_ ))
- : $_->Content
- ),
- \'<br />',
- } @{ $values->ItemsArrayRef };
- pop @values; # Remove that last <br />
- return @values;
- },
- },
Bookmark => {
title => ' ',
value => sub {
@@ -335,8 +315,6 @@ $COLUMN_MAP = {
},
};
-$COLUMN_MAP->{'CF'} = $COLUMN_MAP->{'CustomField'};
-
# if no GPG support, then KeyOwnerName and KeyRequestors fall back to the regular
# versions
if (RT->Config->Get('GnuPG')->{'Enable'}) {
diff --git a/rt/share/html/Elements/SelectQueue b/rt/share/html/Elements/SelectQueue
index 20a5b7d9d..c78afe9ce 100755
--- a/rt/share/html/Elements/SelectQueue
+++ b/rt/share/html/Elements/SelectQueue
@@ -51,7 +51,7 @@
<input name="<%$Name%>" size="25" value="<%$d->Name%>" class="<%$Class%>" />
% }
% else {
-<select name="<%$Name%>" <% ($OnChange) ? 'onchange="'.$OnChange.'"' : '' |n %> class="<%$Class%>">
+<select name="<%$Name%>" <% ($Multiple) ? 'multiple="multiple"' : '' %> <% ($OnChange) ? 'onchange="'.$OnChange.'"' : '' |n %> class="<%$Class%>">
% if ($ShowNullOption) {
<option value="">-</option>
% }
@@ -82,6 +82,7 @@ $NamedValues => 0
$Default => 0
$Lite => 0
$OnChange => undef
+$Multiple => 0
$Class => 'select-queue'
</%args>
<%init>
diff --git a/rt/share/html/Elements/ShowCustomFields b/rt/share/html/Elements/ShowCustomFields
index ddb8b72e3..b60c49ae8 100644
--- a/rt/share/html/Elements/ShowCustomFields
+++ b/rt/share/html/Elements/ShowCustomFields
@@ -45,6 +45,7 @@
%# those contributions and any derivatives thereof.
%#
%# END BPS TAGGED BLOCK }}}
+% $m->callback( CallbackName => 'BeforeCustomFields' );
% if ($Table) {
<table>
% }
@@ -73,6 +74,7 @@
% if ($Table) {
</table>
% }
+% $m->callback( CallbackName => 'AfterCustomFields', Object => $Object );
<%INIT>
$m->callback(
CallbackName => 'MassageCustomFields',
@@ -82,9 +84,10 @@ $m->callback(
my $print_value = sub {
my ($cf, $value) = @_;
- my $linked = $cf->LinkValueTo;
- if ( $linked ) {
- $m->out('<a href="'. $value->LinkValueTo .'" target="_new">');
+ my $linked = $value->LinkValueTo;
+ if ( defined $linked && length $linked ) {
+ my $linked = $m->interp->apply_escapes( $linked, 'h' );
+ $m->out('<a href="'. $linked .'" target="_new">');
}
my $comp = "ShowCustomField". $cf->Type;
$m->callback(
@@ -98,7 +101,7 @@ my $print_value = sub {
} else {
$m->out( $m->interp->apply_escapes( $value->Content, 'h' ) );
}
- $m->out('</a>') if $linked;
+ $m->out('</a>') if defined $linked && length $linked;
# This section automatically populates a div with the "IncludeContentForValue" for this custom
# field if it's been defined
diff --git a/rt/share/html/Elements/ShowLinks b/rt/share/html/Elements/ShowLinks
index 569bad39c..e3b3ef509 100755
--- a/rt/share/html/Elements/ShowLinks
+++ b/rt/share/html/Elements/ShowLinks
@@ -47,7 +47,7 @@
%# END BPS TAGGED BLOCK }}}
<table>
<tr>
- <td class="labeltop"><&|/l&>Depends on</&>: (<a href="<%$clone->{'DependsOn-new'}%>"><% loc('Create') %></a>)</td>
+ <td class="labeltop"><& ShowRelationLabel, id => $id, Label => loc('Depends on'), Relation => 'DependsOn' &>: <span class="create">(<a href="<%$clone->{'DependsOn-new'}%>"><% loc('Create') %></a>)</span></td>
<td class="value">
<%PERL>
@@ -77,7 +77,7 @@ for my $link ( @{ $Ticket->DependsOn->ItemsArrayRef } ) {
</td>
</tr>
<tr>
- <td class="labeltop"><&|/l&>Depended on by</&>: (<a href="<%$clone->{'new-DependsOn'}%>"><% loc('Create') %></a>)</td>
+ <td class="labeltop"><& ShowRelationLabel, id => $id, Label => loc('Depended on by'), Relation => 'DependedOnBy' &>: <span class="create">(<a href="<%$clone->{'new-DependsOn'}%>"><% loc('Create') %></a>)</span></td>
<td class="value">
<ul>
% while (my $Link = $Ticket->DependedOnBy->Next) {
@@ -87,15 +87,15 @@ for my $link ( @{ $Ticket->DependsOn->ItemsArrayRef } ) {
</td>
</tr>
<tr>
- <td class="labeltop"><&|/l&>Parents</&>: (<a href="<%$clone->{'MemberOf-new'}%>"><% loc('Create') %></a>)</td>
+ <td class="labeltop"><& ShowRelationLabel, id => $id, Label => loc('Parents'), Relation => 'Parents' &>: <span class="create">(<a href="<%$clone->{'MemberOf-new'}%>"><% loc('Create') %></a>)</span></td>
<td class="value"><& /Ticket/Elements/ShowParents, Ticket => $Ticket &></td>
</tr>
<tr>
- <td class="labeltop"><&|/l&>Children</&>: (<a href="<%$clone->{'new-MemberOf'}%>"><% loc('Create') %></a>)</td>
+ <td class="labeltop"><& ShowRelationLabel, id => $id, Label => loc('Children'), Relation => 'Children' &>: <span class="create">(<a href="<%$clone->{'new-MemberOf'}%>"><% loc('Create') %></a>)</span></td>
<td class="value"><& /Ticket/Elements/ShowMembers, Ticket => $Ticket &></td>
</tr>
<tr>
- <td class="labeltop"><&|/l&>Refers to</&>: (<a href="<%$clone->{'RefersTo-new'}%>"><% loc('Create') %></a>)</td>
+ <td class="labeltop"><& ShowRelationLabel, id => $id, Label => loc('Refers to'), Relation => 'RefersTo' &>: <span class="create">(<a href="<%$clone->{'RefersTo-new'}%>"><% loc('Create') %></a>)</span></td>
<td class="value">
<ul>
% while (my $Link = $Ticket->RefersTo->Next) {
@@ -105,7 +105,7 @@ for my $link ( @{ $Ticket->DependsOn->ItemsArrayRef } ) {
</td>
</tr>
<tr>
- <td class="labeltop"><&|/l&>Referred to by</&>: (<a href="<%$clone->{'new-RefersTo'}%>"><% loc('Create') %></a>)</td>
+ <td class="labeltop"><& ShowRelationLabel, id => $id, Label => loc('Referred to by'), Relation => 'ReferredToBy' &>: <span class="create">(<a href="<%$clone->{'new-RefersTo'}%>"><% loc('Create') %></a>)</span></td>
<td class="value">
<ul>
% while (my $Link = $Ticket->ReferredToBy->Next) {
@@ -124,14 +124,15 @@ for my $link ( @{ $Ticket->DependsOn->ItemsArrayRef } ) {
<%INIT>
+my $id = $Ticket->id;
+
my $clone = {};
my $path
= RT->Config->Get('WebPath')
. '/Ticket/Create.html?Queue='
. $Ticket->Queue
. '&CloneTicket='
- . $Ticket->id;
-
+ . $id;
for my $relation (
qw(RefersTo ReferredToBy)) {
@@ -142,15 +143,14 @@ for my $relation (
$clone->{$field}
= $path . "&$field="
. join( '%20',
- ( map { $_->$other() } @{ $Ticket->$relation->ItemsArrayRef } ),
- $Ticket->id );
+ ( map { $_->$other() } @{ $Ticket->$relation->ItemsArrayRef } ), $id );
}
for my $relation ( qw(MemberOf Members DependsOn DependedOnBy)) {
my $mode = $RT::Ticket::LINKTYPEMAP{$relation}->{Mode};
my $type = $RT::Ticket::LINKTYPEMAP{$relation}->{Type};
my $field = $mode eq 'Base' ? 'new-' . $type : $type . '-new';
- $clone->{$field} = $path . "&$field=". $Ticket->id ;
+ $clone->{$field} = $path . "&$field=$id";
}
</%INIT>
diff --git a/rt/share/html/Elements/ShowRelationLabel b/rt/share/html/Elements/ShowRelationLabel
new file mode 100644
index 000000000..3c1ed1514
--- /dev/null
+++ b/rt/share/html/Elements/ShowRelationLabel
@@ -0,0 +1,62 @@
+%# BEGIN BPS TAGGED BLOCK {{{
+%#
+%# COPYRIGHT:
+%#
+%# This software is Copyright (c) 1996-2009 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., 51 Franklin Street, Fifth Floor, Boston, MA
+%# 02110-1301 or visit their web page on the internet at
+%# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html.
+%#
+%#
+%# CONTRIBUTION SUBMISSION POLICY:
+%#
+%# (The following paragraph is not intended to limit the rights granted
+%# to you to modify and distribute this software under the terms of
+%# the GNU General Public License and is only of importance to you if
+%# you choose to contribute your changes and enhancements to the
+%# community by submitting them to Best Practical Solutions, LLC.)
+%#
+%# By intentionally submitting any modifications, corrections or
+%# derivatives to this work, or any other work intended for use with
+%# Request Tracker, to Best Practical Solutions, LLC, you confirm that
+%# you are the copyright holder for those contributions and you grant
+%# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable,
+%# royalty-free, perpetual, license to use, copy, create derivative
+%# works based on those contributions, and sublicense and distribute
+%# those contributions and any derivatives thereof.
+%#
+%# END BPS TAGGED BLOCK }}}
+<a href="<%$SearchURL |n %>"><%$Label%></a>
+<%INIT>
+my $typemap = RT::Ticket->LINKTYPEMAP->{$Relation};
+my $search_mode = $typemap->{Mode};
+my $search_type = $typemap->{Type};
+my $search_relation = RT::Ticket->LINKDIRMAP->{$search_type}{$search_mode};
+
+my $Query = $search_relation . ' = ' . $id;
+my $SearchURL = RT->Config->Get('WebPath') . '/Search/Results.html?' . $m->comp('/Elements/QueryString', Query => $Query);
+</%INIT>
+<%ARGS>
+$id
+$Label
+$Relation
+</%ARGS>
diff --git a/rt/share/html/Elements/ShowUser b/rt/share/html/Elements/ShowUser
index 2fbdcbc3e..01de7256a 100644
--- a/rt/share/html/Elements/ShowUser
+++ b/rt/share/html/Elements/ShowUser
@@ -49,18 +49,20 @@
<%INIT>
# $User is an RT::User object
# $Address is Email::Address object
-if ( !$User && $Address ) {
- $User = RT::User->new( $session{'CurrentUser'} );
- $User->LoadByEmail( $Address->address );
- unless ( $User->Id ) {
- $m->comp( '/Elements/ShowUserVerbose', Address => $Address );
- return;
- }
+
+my $comp = '/Elements/ShowUser'. ucfirst lc $style;
+unless ( $m->comp_exists( $comp ) ) {
+ $RT::Logger->error(
+ 'Either system config or user #'
+ . $session{'CurrentUser'}->id
+ . ' picked UsernameFormat '. $style
+ . ', but '. $comp . "doesn't exist"
+ );
+ return $m->comp('/Elements/ShowUserConcise',
+ User => $User, Address => $Address,
+ );
}
-if ( $style eq 'concise' ) {
- $m->comp( '/Elements/ShowUserConcise', User => $User );
-}
-else { $m->comp( '/Elements/ShowUserVerbose', User => $User ); }
+return $m->comp( $comp, User => $User, Address => $Address );
</%INIT>
<%ARGS>
$User => undef
diff --git a/rt/share/html/Elements/ShowUserConcise b/rt/share/html/Elements/ShowUserConcise
index 3cdba10dd..c4cccca75 100644
--- a/rt/share/html/Elements/ShowUserConcise
+++ b/rt/share/html/Elements/ShowUserConcise
@@ -46,7 +46,19 @@
%#
%# END BPS TAGGED BLOCK }}}
%# Released under the terms of version 2 of the GNU Public License
-<% $User->RealName || $User->Name %>\
+<% $Address || $User->RealName || $User->Name %>\
<%ARGS>
-$User
+$User => undef
+$Address => undef
</%ARGS>
+<%INIT>
+if ( !$User && $Address ) {
+ $User = RT::User->new( $session{'CurrentUser'} );
+ $User->LoadByEmail( $Address->address );
+ if ( $User->Id ) {
+ $Address = '';
+ } else {
+ $Address = $Address->address;
+ }
+}
+</%INIT>
diff --git a/rt/share/html/Helpers/CalPopup.html b/rt/share/html/Helpers/CalPopup.html
index 96e8d77d0..70b43c192 100644
--- a/rt/share/html/Helpers/CalPopup.html
+++ b/rt/share/html/Helpers/CalPopup.html
@@ -123,7 +123,17 @@ elsif ($DisplayedMonth == 1) {
$prev_year--;
}
-my @cal = calendar($DisplayedMonth, $DisplayedYear);
+my @cal;
+{
+ my $error;
+ # RT defines a __DIE__ and Calendar::Simple uses Carp::Croak to report errors
+ # work around this so we get a better error message if something is out of range
+ eval { local $SIG{__DIE__} = sub { $error = $_[0] }; @cal = calendar($DisplayedMonth, $DisplayedYear) };
+ if ($error) {
+ $RT::Logger->error("error $error");
+ $m->comp('/Elements/Error', Why => $error );
+ }
+}
</%init>
<%args>
diff --git a/rt/share/html/NoAuth/Logout.html b/rt/share/html/NoAuth/Logout.html
index 5a4926b97..7b80823b3 100755
--- a/rt/share/html/NoAuth/Logout.html
+++ b/rt/share/html/NoAuth/Logout.html
@@ -45,7 +45,7 @@
%# those contributions and any derivatives thereof.
%#
%# END BPS TAGGED BLOCK }}}
-<& /Elements/Header, Title => loc('Logout'), Refresh => "1;URL=$URL" &>
+<& /Elements/Header, Title => loc('Logout'), Refresh => RT->Config->Get('LogoutRefresh').";URL=$URL" &>
</div>
<div id="body" class="login-body">
@@ -58,22 +58,22 @@
<br />
<a href="<%$URL%>"><&|/l&>You're welcome to login again</&></a>.
</&>
+
+% $m->callback( %ARGS );
+
</div></div>
<& /Elements/Footer, Menu => 0 &>
% $m->abort();
<%INIT>
+my $URL = RT->Config->Get('WebPath')."/";
$m->callback( %ARGS, CallbackName => 'BeforeSessionDelete' );
-if (defined %session) {
+if (keys %session) {
tied(%session)->delete;
$session{'CurrentUser'} = RT::CurrentUser->new;
}
$m->callback( %ARGS, CallbackName => 'AfterSessionDelete' );
</%INIT>
-
-<%ARGS>
-$URL => RT->Config->Get('WebPath')."/"
-</%ARGS>
diff --git a/rt/share/html/NoAuth/css/3.4-compat/misc.css b/rt/share/html/NoAuth/css/3.4-compat/misc.css
index 2a58b13aa..a7a445f84 100644
--- a/rt/share/html/NoAuth/css/3.4-compat/misc.css
+++ b/rt/share/html/NoAuth/css/3.4-compat/misc.css
@@ -45,6 +45,9 @@
%# those contributions and any derivatives thereof.
%#
%# END BPS TAGGED BLOCK }}}
+
+@import "../base/misc.css";
+
.oddline { background: white; }
.evenline { background: #cecfef; }
diff --git a/rt/share/html/NoAuth/css/3.4-compat/titlebox.css b/rt/share/html/NoAuth/css/3.4-compat/titlebox.css
index 9b31b294b..72b1a27cb 100644
--- a/rt/share/html/NoAuth/css/3.4-compat/titlebox.css
+++ b/rt/share/html/NoAuth/css/3.4-compat/titlebox.css
@@ -77,10 +77,6 @@
color: black;
}
-.titlebox .titlebox-content hr.clear {
- visibility: hidden;
-}
-
%# TRS: I wish there was a more elegant way to do this... I essentially need to
%# select all elements X that do NOT have element Y as a descendant... which I can
%# fake with the child selector of CSS2, but IE is stupid and does not support that.
diff --git a/rt/share/html/NoAuth/css/3.5-default/misc.css b/rt/share/html/NoAuth/css/3.5-default/misc.css
index 67b5e1951..ca5020338 100755
--- a/rt/share/html/NoAuth/css/3.5-default/misc.css
+++ b/rt/share/html/NoAuth/css/3.5-default/misc.css
@@ -45,6 +45,9 @@
%# those contributions and any derivatives thereof.
%#
%# END BPS TAGGED BLOCK }}}
+
+@import "../base/misc.css";
+
body {
font-family: Verdana, sans-serif;
font-size: 76%;
@@ -52,8 +55,6 @@ body {
background-color: white;
}
-.hide, .hidden { display: none !important; }
-
#body.calpopup {
margin-left: 2em;
}
@@ -77,36 +78,11 @@ td {
padding: 0.1em 0.5em 0.1em 0.5em;
}
-.clear { clear: both; }
-
ul.action-results {
margin-top: 0;
margin-bottom: 0;
}
-div.autocomplete {
- position: absolute;
- background-color: white;
- border: 1px solid #888;
- margin: 0px;
- padding: 0px;
-}
-div.autocomplete ul {
- list-style-type: none;
- margin: 0px;
- padding: 0px;
-}
-div.autocomplete ul li.selected {
- background-color: #0088cc;
- color: #eee;
-}
-div.autocomplete ul li {
- list-style-type: none;
- display: block;
- margin: 0;
- padding: 2px;
-}
-
.shredder-form { line-height: 3em }
.shredder-form span { margin-left: 1em; margin-right: 1em }
.shredder-help {
@@ -122,4 +98,3 @@ div.autocomplete ul li {
#shredder-plugin-results input { margin-left: 1em; }
.pod-sequence-C { background-color: #eee }
-
diff --git a/rt/share/html/NoAuth/css/3.5-default/titlebox.css b/rt/share/html/NoAuth/css/3.5-default/titlebox.css
index 329cf8f76..f47b15803 100644
--- a/rt/share/html/NoAuth/css/3.5-default/titlebox.css
+++ b/rt/share/html/NoAuth/css/3.5-default/titlebox.css
@@ -152,10 +152,6 @@
text-decoration: underline;
}
-.titlebox .titlebox-content hr.clear {
- visibility: hidden;
-}
-
.titlebox .titlebox-title .left {
position: relative;
}
diff --git a/rt/share/html/NoAuth/css/autohandler b/rt/share/html/NoAuth/css/autohandler
index a92cfd17b..f11f78adb 100644
--- a/rt/share/html/NoAuth/css/autohandler
+++ b/rt/share/html/NoAuth/css/autohandler
@@ -49,7 +49,8 @@
my $file = $m->base_comp->source_file;
if ($file =~ /\.(gif|png|jpe?g)$/i) {
- RT::Interface::Web->SendStaticFile( File => $file );
+ my $relfile = $m->base_comp->path;
+ RT::Interface::Web->SendStaticFile( File => $file, RelativeFile => $relfile );
} else {
RT::Interface::Web::StaticFileHeaders();
$r->content_type('text/css') ;
diff --git a/rt/share/html/NoAuth/css/base/misc.css b/rt/share/html/NoAuth/css/base/misc.css
new file mode 100644
index 000000000..84023eca9
--- /dev/null
+++ b/rt/share/html/NoAuth/css/base/misc.css
@@ -0,0 +1,49 @@
+.hide, .hidden { display: none !important; }
+
+div.autocomplete {
+ position: absolute;
+ background-color: white;
+ border: 1px solid #888;
+ margin: 0px;
+ padding: 0px;
+}
+div.autocomplete ul {
+ list-style-type: none;
+ margin: 0px;
+ padding: 0px;
+}
+div.autocomplete ul li.selected {
+ background-color: #0088cc;
+ color: #eee;
+}
+div.autocomplete ul li {
+ list-style-type: none;
+ display: block;
+ margin: 0;
+ padding: 2px;
+}
+
+
+.clear { clear: both; }
+
+* html .clearfix {
+ height: 1%; /* IE5-6 */
+}
+.clearfix {
+ display: inline-block; /* IE7xhtml*/
+}
+html[xmlns] .clearfix { /* O */
+ display: block;
+}
+.clearfix:after { /* FF, O, etc. */
+ content: ".";
+ display: block;
+ height: 0;
+ clear: both;
+ visibility: hidden;
+}
+
+.titlebox .titlebox-content hr.clear {
+ visibility: hidden;
+}
+
diff --git a/rt/share/html/NoAuth/css/print.css b/rt/share/html/NoAuth/css/print.css
index aaa1e8a2a..ae50342d8 100644
--- a/rt/share/html/NoAuth/css/print.css
+++ b/rt/share/html/NoAuth/css/print.css
@@ -80,7 +80,16 @@ div#header h1 {
#header #page-menu,
#header #actions-menu,
#header #page-navigation,
-.titlebox .title .widget,
+.titlebox .titlebox-title .widget,
+.ticket-info-links .titlebox-title .right,
+.ticket-info-links .titlebox-content .labeltop .create,
+.history .titlebox .titlebox-title .right,
+.ticket-transaction .metadata .actions,
+.ticket-transaction .content .downloadattachment,
+#comp-Search-Results #body .refresh,
+.search-result-actions,
+#comp-Search-Chart #body div,
+#comp-Search-Chart #body form,
#footer
{
display: none;
diff --git a/rt/share/html/NoAuth/css/web2/base.css b/rt/share/html/NoAuth/css/web2/base.css
index b98253af9..a38854fb5 100644
--- a/rt/share/html/NoAuth/css/web2/base.css
+++ b/rt/share/html/NoAuth/css/web2/base.css
@@ -45,13 +45,6 @@
%# those contributions and any derivatives thereof.
%#
%# END BPS TAGGED BLOCK }}}
-.hide { display: none; }
-.clear { display: none;}
-
-
-
-
-
a {
color: #000;
text-decoration: none;
diff --git a/rt/share/html/NoAuth/css/web2/boxes.css b/rt/share/html/NoAuth/css/web2/boxes.css
index 0f2f20c2b..fbd9af108 100644
--- a/rt/share/html/NoAuth/css/web2/boxes.css
+++ b/rt/share/html/NoAuth/css/web2/boxes.css
@@ -160,10 +160,6 @@
}
-.hidden {
- display: none;
-}
-
.titlebox .titlebox-title .widget a {
display: block;
margin: 0;
@@ -190,3 +186,7 @@
.titlebox.rolled-up .titlebox-title .widget a {
background-image: url(<%RT->Config->Get('WebPath')%>/NoAuth/images/css/rolldown-arrow.gif);
}
+
+.titlebox hr.clear {
+ display: none;
+}
diff --git a/rt/share/html/NoAuth/css/web2/collection.css b/rt/share/html/NoAuth/css/web2/collection.css
new file mode 100644
index 000000000..cbc8cefd7
--- /dev/null
+++ b/rt/share/html/NoAuth/css/web2/collection.css
@@ -0,0 +1,52 @@
+%# BEGIN BPS TAGGED BLOCK {{{
+%#
+%# COPYRIGHT:
+%#
+%# This software is Copyright (c) 1996-2009 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., 51 Franklin Street, Fifth Floor, Boston, MA
+%# 02110-1301 or visit their web page on the internet at
+%# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html.
+%#
+%#
+%# CONTRIBUTION SUBMISSION POLICY:
+%#
+%# (The following paragraph is not intended to limit the rights granted
+%# to you to modify and distribute this software under the terms of
+%# the GNU General Public License and is only of importance to you if
+%# you choose to contribute your changes and enhancements to the
+%# community by submitting them to Best Practical Solutions, LLC.)
+%#
+%# By intentionally submitting any modifications, corrections or
+%# derivatives to this work, or any other work intended for use with
+%# Request Tracker, to Best Practical Solutions, LLC, you confirm that
+%# you are the copyright holder for those contributions and you grant
+%# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable,
+%# royalty-free, perpetual, license to use, copy, create derivative
+%# works based on those contributions, and sublicense and distribute
+%# those contributions and any derivatives thereof.
+%#
+%# END BPS TAGGED BLOCK }}}
+
+table.collection td:first-child, table.collection th:first-child {
+ padding-left: 1em;
+}
+
diff --git a/rt/share/html/NoAuth/css/web2/main.css b/rt/share/html/NoAuth/css/web2/main.css
index 5ca561456..a47700354 100644
--- a/rt/share/html/NoAuth/css/web2/main.css
+++ b/rt/share/html/NoAuth/css/web2/main.css
@@ -62,6 +62,7 @@
@import "ticket.css";
@import "tools.css";
@import "admin.css";
+@import "collection.css";
@import "misc.css";
% $m->callback(CallbackName => 'End');
diff --git a/rt/share/html/NoAuth/css/web2/misc.css b/rt/share/html/NoAuth/css/web2/misc.css
index eef5f4876..80d7ce0b4 100644
--- a/rt/share/html/NoAuth/css/web2/misc.css
+++ b/rt/share/html/NoAuth/css/web2/misc.css
@@ -45,6 +45,9 @@
%# those contributions and any derivatives thereof.
%#
%# END BPS TAGGED BLOCK }}}
+
+@import "../base/misc.css";
+
#body.calpopup {
margin-left: 1em;
margin-top: 1em;
@@ -71,29 +74,6 @@
font-size: 1.5em;
}
-div.autocomplete {
- position: absolute;
- background-color: white;
- border: 1px solid #888;
- margin: 0px;
- padding: 0px;
-}
-div.autocomplete ul {
- list-style-type: none;
- margin: 0px;
- padding: 0px;
-}
-div.autocomplete ul li.selected {
- background-color: #0088cc;
- color: #eee;
-}
-div.autocomplete ul li {
- list-style-type: none;
- display: block;
- margin: 0;
- padding: 2px;
-}
-
.comment {
padding-left: 0.5em;
color: #999;
@@ -105,4 +85,3 @@ div.autocomplete ul li {
margin-top: 1em;
overflow: auto;
}
-
diff --git a/rt/share/html/NoAuth/css/web2/msie.css b/rt/share/html/NoAuth/css/web2/msie.css
index 184ac1df5..2297c304a 100644
--- a/rt/share/html/NoAuth/css/web2/msie.css
+++ b/rt/share/html/NoAuth/css/web2/msie.css
@@ -237,3 +237,10 @@ table.queue-summary td, td.collection-as-table {
#pick-criteria td.operator {
width: 7.5em;
}
+
+.plain-text-white-space {
+ word-wrap: break-word; /* Internet Explorer 5.5+ */
+ white-space: pre; /* IE only hack to re-specify in addition to
+ word-wrap */
+}
+
diff --git a/rt/share/html/NoAuth/css/web2/portlets.css b/rt/share/html/NoAuth/css/web2/portlets.css
index 947f49db2..d96d5a9f0 100644
--- a/rt/share/html/NoAuth/css/web2/portlets.css
+++ b/rt/share/html/NoAuth/css/web2/portlets.css
@@ -63,3 +63,9 @@ table.dashboard {
}
+.reminders blockquote {
+ margin-top: 0.5em;
+ margin-bottom: 0.5em;
+ margin-left: 1em;
+ margin-right: 1em;
+}
diff --git a/rt/share/html/NoAuth/images/autohandler b/rt/share/html/NoAuth/images/autohandler
index 431a44f1d..7abf8b89e 100644
--- a/rt/share/html/NoAuth/images/autohandler
+++ b/rt/share/html/NoAuth/images/autohandler
@@ -3,5 +3,6 @@
# properly configured their webserver to stop RT from passing
# images through the mason handler.
my $file = $m->base_comp->source_file;
-RT::Interface::Web->SendStaticFile( File => $file );
+my $relfile = $m->base_comp->path;
+RT::Interface::Web->SendStaticFile( File => $file, RelativeFile => $relfile );
</%INIT>
diff --git a/rt/share/html/NoAuth/js/autohandler b/rt/share/html/NoAuth/js/autohandler
index 74028f8c6..e81415433 100644
--- a/rt/share/html/NoAuth/js/autohandler
+++ b/rt/share/html/NoAuth/js/autohandler
@@ -51,7 +51,8 @@ my $type;
my $file = $m->base_comp->source_file;
if ($file =~ /\.(gif|png|jpe?g)$/i) {
- RT::Interface::Web->SendStaticFile( File => $file );
+ my $relfile = $m->base_comp->path;
+ RT::Interface::Web->SendStaticFile( File => $file, RelativeFile => $relfile );
} else {
&RT::Interface::Web::StaticFileHeaders();
$r->content_type('application/x-javascript');
diff --git a/rt/share/html/NoAuth/rss/dhandler b/rt/share/html/NoAuth/rss/dhandler
new file mode 100644
index 000000000..c402b6f8e
--- /dev/null
+++ b/rt/share/html/NoAuth/rss/dhandler
@@ -0,0 +1,48 @@
+%# BEGIN BPS TAGGED BLOCK {{{
+%#
+%# COPYRIGHT:
+%#
+%# This software is Copyright (c) 1996-2009 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., 51 Franklin Street, Fifth Floor, Boston, MA
+%# 02110-1301 or visit their web page on the internet at
+%# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html.
+%#
+%#
+%# CONTRIBUTION SUBMISSION POLICY:
+%#
+%# (The following paragraph is not intended to limit the rights granted
+%# to you to modify and distribute this software under the terms of
+%# the GNU General Public License and is only of importance to you if
+%# you choose to contribute your changes and enhancements to the
+%# community by submitting them to Best Practical Solutions, LLC.)
+%#
+%# By intentionally submitting any modifications, corrections or
+%# derivatives to this work, or any other work intended for use with
+%# Request Tracker, to Best Practical Solutions, LLC, you confirm that
+%# you are the copyright holder for those contributions and you grant
+%# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable,
+%# royalty-free, perpetual, license to use, copy, create derivative
+%# works based on those contributions, and sublicense and distribute
+%# those contributions and any derivatives thereof.
+%#
+%# END BPS TAGGED BLOCK }}}
+<& /Search/Elements/ResultsRSSView, %ARGS &>
diff --git a/rt/share/html/Search/Bulk.html b/rt/share/html/Search/Bulk.html
index fa20e331c..f2ca45c26 100755
--- a/rt/share/html/Search/Bulk.html
+++ b/rt/share/html/Search/Bulk.html
@@ -163,7 +163,9 @@
<input type="submit" class="button" name="AddMoreAttach" value="<&|/l&>Add More Files</&>" />
<input type="hidden" class="hidden" name="UpdateAttach" value="1" /></td></tr>
<tr><td class="labeltop"><&|/l&>Message</&>:</td><td>
- <& /Elements/MessageBox, Name=>"UpdateContent"&>
+%# Currently, bulk update always starts with Comment not Reply selected, so we check this unconditionally
+% my $IncludeSignature = RT->Config->Get('MessageBoxIncludeSignatureOnComment');
+<& /Elements/MessageBox, Name => "UpdateContent", IncludeSignature => $IncludeSignature &>
</td></tr>
</table>
diff --git a/rt/share/html/Search/Chart b/rt/share/html/Search/Chart
index 59e9fc6fc..abee3e52a 100644
--- a/rt/share/html/Search/Chart
+++ b/rt/share/html/Search/Chart
@@ -66,52 +66,11 @@ if ($ChartStyle eq 'pie') {
use RT::Report::Tickets;
my $tix = RT::Report::Tickets->new( $session{'CurrentUser'} );
+
my ($count_name, $value_name) = $tix->SetupGroupings(
Query => $Query, GroupBy => $PrimaryGroupBy,
);
-my $chart = $chart_class->new( 600 => 400 );
-
-my $font = RT->Config->Get('ChartFont') || ['verdana', 'arial', gdMediumBoldFont];
-$chart->set_title_font( $font, 12 ) if $chart->can('set_title_font');
-$chart->set_legend_font( $font, 12 ) if $chart->can('set_legend_font');
-$chart->set_x_label_font( $font, 10 ) if $chart->can('set_x_label_font');
-$chart->set_y_label_font( $font, 10 ) if $chart->can('set_y_label_font');
-$chart->set_label_font( $font, 10 ) if $chart->can('set_label_font');
-$chart->set_x_axis_font( $font, 9 ) if $chart->can('set_x_axis_font');
-$chart->set_y_axis_font( $font, 9 ) if $chart->can('set_y_axis_font');
-$chart->set_values_font( $font, 9 ) if $chart->can('set_values_font');
-$chart->set_value_font( $font, 9 ) if $chart->can('set_value_font');
-
-# Pie charts don't like having no input, so we show a special image
-# that indicates an error message. Because this is used in an <img>
-# context, it can't be a simple error message. Without this check,
-# the chart will just be a non-loading image.
-if ($tix->Count == 0) {
- my $plot = GD::Image->new(600 => 400);
- $plot->colorAllocate(255, 255, 255); # background
- my $black = $plot->colorAllocate(0, 0, 0);
-
- require GD::Text::Wrap;
- my $error = GD::Text::Wrap->new($plot,
- color => $black,
- text => loc("No tickets found."),
- );
- $error->set_font( $font, 12 );
- $error->draw(0, 0);
-
- $m->comp( 'SELF:Plot', plot => $plot, %ARGS );
-}
-
-if ($chart_class eq "GD::Graph::bars") {
- $chart->set(
- x_label => $tix->Label( $PrimaryGroupBy ),
- x_labels_vertical => 1,
- y_label => loc('Tickets'),
- show_values => 1
- );
-}
-
my %class = (
Queue => 'RT::Queue',
Owner => 'RT::User',
@@ -121,15 +80,17 @@ my %class = (
my $class = $class{ $PrimaryGroupBy };
my %data;
+my $max_value = 0;
+my $max_key_length = 0;
while ( my $entry = $tix->Next ) {
my $key;
if ( $class ) {
my $q = $class->new( $session{'CurrentUser'} );
- $q->Load( $entry->__Value( $value_name ) );
+ $q->Load( $entry->LabelValue( $value_name ) );
$key = $q->Name;
}
else {
- $key = $entry->__Value($value_name);
+ $key = $entry->LabelValue($value_name);
}
$key ||= '(no value)';
@@ -140,26 +101,84 @@ while ( my $entry = $tix->Next ) {
$key = loc($key);
}
$data{ $key } = $value;
-}
-
-# XXX: Convert 1970-01-01 date to the 'Not Set'
-# this code should be generalized!!!
-if ( $PrimaryGroupBy =~ /(Daily|Monthly|Annually)$/ ) {
- my $re;
- $re = qr{1970-01-01} if $PrimaryGroupBy =~ /Daily$/;
- $re = qr{1970-01} if $PrimaryGroupBy =~ /Monthly$/;
- $re = qr{1970} if $PrimaryGroupBy =~ /Annually$/;
- foreach my $k (keys %data) {
- my $tmp = $k;
- $tmp =~ s/^$re/loc('Not Set')/e or next;
- $data{$tmp} = delete $data{$k};
- }
+ $max_value = $value if $max_value < $value;
+ $max_key_length = length $key if $max_key_length < length $key;
}
unless (keys %data) {
$data{''} = 0;
}
+
+my $chart = $chart_class->new( 600 => 400 );
+$chart->set( pie_height => 60 ) if $chart_class eq 'GD::Graph::pie';
+my %font_config = RT->Config->Get('ChartFont');
+my $font = $font_config{ $session{CurrentUser}->UserObj->Lang || '' }
+ || $font_config{'others'};
+$chart->set_title_font( $font, 16 ) if $chart->can('set_title_font');
+$chart->set_legend_font( $font, 16 ) if $chart->can('set_legend_font');
+$chart->set_x_label_font( $font, 14 ) if $chart->can('set_x_label_font');
+$chart->set_y_label_font( $font, 14 ) if $chart->can('set_y_label_font');
+$chart->set_label_font( $font, 14 ) if $chart->can('set_label_font');
+$chart->set_x_axis_font( $font, 12 ) if $chart->can('set_x_axis_font');
+$chart->set_y_axis_font( $font, 12 ) if $chart->can('set_y_axis_font');
+$chart->set_values_font( $font, 12 ) if $chart->can('set_values_font');
+$chart->set_value_font( $font, 12 ) if $chart->can('set_value_font');
+
+# Pie charts don't like having no input, so we show a special image
+# that indicates an error message. Because this is used in an <img>
+# context, it can't be a simple error message. Without this check,
+# the chart will just be a non-loading image.
+if ($tix->Count == 0) {
+ my $plot = GD::Image->new(600 => 400);
+ $plot->colorAllocate(255, 255, 255); # background
+ my $black = $plot->colorAllocate(0, 0, 0);
+
+ require GD::Text::Wrap;
+ my $error = GD::Text::Wrap->new($plot,
+ color => $black,
+ text => loc("No tickets found."),
+ );
+ $error->set_font( $font, 16 );
+ $error->draw(0, 0);
+
+ $m->comp( 'SELF:Plot', plot => $plot, %ARGS );
+}
+
+if ($chart_class eq "GD::Graph::bars") {
+ $chart->set(
+ x_label => $tix->Label( $PrimaryGroupBy ),
+ y_label => loc('Tickets'),
+ show_values => 1,
+ bar_spacing => 5,
+ bargroup_spacing => 10,
+ x_label_position => 0.6,
+ y_label_position => 0.6,
+ values_space => -1,
+# the following line to make sure there's enough space for values to show
+ y_max_value => 5*(int($max_value/5) + 2),
+# if there're too many bars or at least one key is too long, use vertical
+ x_labels_vertical => ( keys(%data) * $max_key_length > 60 ) ? 1 : 0,
+ );
+}
+
+# refine values' colors, with both Color::Scheme's help and my own tweak
+$chart->{dclrs} = [
+ '66cc66', 'ff6666', 'ffcc66', '663399',
+ '3333cc',
+ '339933', '993333', '996633', '663399',
+ '33cc33', 'cc3333', 'cc9933', '6633cc'
+];
+
+{
+ no warnings 'redefine';
+ *GD::Graph::pick_data_clr = sub {
+ my $self = shift;
+ my $color_hex = $self->{dclrs}[ $_[0] % @{ $self->{dclrs} } - 1 ];
+ return map { hex } ( $color_hex =~ /(..)(..)(..)/ );
+ };
+}
+
my $plot = $chart->plot( [ [sort keys %data], [map $data{$_}, sort keys %data] ] ) or die $chart->error;
$m->comp( 'SELF:Plot', plot => $plot, %ARGS );
</%init>
@@ -170,7 +189,6 @@ $plot => undef
</%ARGS>
<%INIT>
my @types = ('png', 'gif');
-
for my $type (@types) {
$plot->can($type)
or next;
diff --git a/rt/share/html/Search/Elements/Chart b/rt/share/html/Search/Elements/Chart
index 3db92c4d8..bf4cd0c1c 100644
--- a/rt/share/html/Search/Elements/Chart
+++ b/rt/share/html/Search/Elements/Chart
@@ -72,28 +72,16 @@ my (@keys, @values);
while ( my $entry = $tix->Next ) {
if ($class) {
my $q = $class->new( $session{'CurrentUser'} );
- $q->Load( $entry->__Value( $value_name ) );
+ $q->Load( $entry->LabelValue( $value_name ) );
push @keys, $q->Name;
}
else {
- push @keys, $entry->__Value( $value_name );
+ push @keys, $entry->LabelValue( $value_name );
}
$keys[-1] ||= loc('(no value)');
push @values, $entry->__Value( $count_name );
}
-# XXX: Convert 1970-01-01 date to the 'Not Set'
-# this code should be generalized!!!
-if ( $PrimaryGroupBy =~ /(Daily|Monthly|Annually)$/ ) {
- my $re;
- $re = qr{1970-01-01} if $PrimaryGroupBy =~ /Daily$/;
- $re = qr{1970-01} if $PrimaryGroupBy =~ /Monthly$/;
- $re = qr{1970} if $PrimaryGroupBy =~ /Annually$/;
- foreach (@keys) {
- s/^$re/loc('Not Set')/e;
- }
-}
-
my %data;
my %loc_keys;
foreach my $key (@keys) { $data{$key} = shift @values; $loc_keys{$key} = loc($key); }
@@ -126,7 +114,23 @@ my $query_string = $m->comp('/Elements/QueryString', %ARGS);
% $total += $value;
<tr class="<%$i%2 ? 'evenline' : 'oddline' %>">
<td class="label collection-as-table">
-<%$key%>
+%# TODO sadly we don't have "creator.city is null" or alike support yet
+%# so no link if the key is undef for now
+% if ( $PrimaryGroupBy !~ /(Hourly|Daily|Monthly|Annually)$/
+% && $key ne loc('(no value)') ) {
+% my $group = $PrimaryGroupBy; $group =~ s! !.!;
+% my %orig_keys = reverse %loc_keys;
+% my $QueryString = $m->comp('/Elements/QueryString',
+% Query => "$Query and $group = '$orig_keys{$key}'",
+% Format => $ARGS{Format},
+% Rows => $ARGS{Rows},
+% OrderBy => $ARGS{OrderBy},
+% Order => $ARGS{Order},
+% );
+<a href=<% RT->Config->Get('WebURL') %>Search/Results.html?<%$QueryString%>><%$key%></a>
+% } else {
+<% $key %>
+% }
</td>
<td class="value collection-as-table">
<%$value%>
diff --git a/rt/share/html/Search/Elements/ResultsRSSView b/rt/share/html/Search/Elements/ResultsRSSView
new file mode 100644
index 000000000..f335411f8
--- /dev/null
+++ b/rt/share/html/Search/Elements/ResultsRSSView
@@ -0,0 +1,143 @@
+%# BEGIN BPS TAGGED BLOCK {{{
+%#
+%# COPYRIGHT:
+%#
+%# This software is Copyright (c) 1996-2009 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., 51 Franklin Street, Fifth Floor, Boston, MA
+%# 02110-1301 or visit their web page on the internet at
+%# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html.
+%#
+%#
+%# CONTRIBUTION SUBMISSION POLICY:
+%#
+%# (The following paragraph is not intended to limit the rights granted
+%# to you to modify and distribute this software under the terms of
+%# the GNU General Public License and is only of importance to you if
+%# you choose to contribute your changes and enhancements to the
+%# community by submitting them to Best Practical Solutions, LLC.)
+%#
+%# By intentionally submitting any modifications, corrections or
+%# derivatives to this work, or any other work intended for use with
+%# Request Tracker, to Best Practical Solutions, LLC, you confirm that
+%# you are the copyright holder for those contributions and you grant
+%# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable,
+%# royalty-free, perpetual, license to use, copy, create derivative
+%# works based on those contributions, and sublicense and distribute
+%# those contributions and any derivatives thereof.
+%#
+%# END BPS TAGGED BLOCK }}}
+<%INIT>
+use Encode ();
+
+my $old_current_user;
+
+if ( $m->request_comp->path =~ RT->Config->Get('WebNoAuthRegex') ) {
+ my $path = $m->dhandler_arg;
+
+ my $notfound = sub {
+ my $mesg = shift;
+ $r->headers_out->{'Status'} = '404 Not Found';
+ $RT::Logger->info("Error encountered in rss generation: $mesg");
+ $m->clear_and_abort;
+ };
+
+ $notfound->("Invalid path: $path") unless $path =~ m!^([^/]+)/([^/]+)/?!;
+
+ my ( $name, $auth ) = ( $1, $2 );
+
+ # Unescape parts
+ $name =~ s/\%([0-9a-z]{2})/chr(hex($1))/gei;
+
+ # convert to perl strings
+ $name = Encode::decode_utf8($name);
+
+ my $user = RT::User->new($RT::SystemUser);
+ $user->Load($name);
+ $notfound->("Invalid user: $user") unless $user->id;
+
+ $notfound->("Invalid authstring")
+ unless $user->ValidateAuthString( $auth,
+ $ARGS{Query} . $ARGS{Order} . $ARGS{OrderBy} );
+
+ $old_current_user = $session{'CurrentUser'};
+ my $cu = RT::CurrentUser->new;
+ $cu->Load($user);
+ $session{'CurrentUser'} = $cu;
+}
+
+my $Tickets = RT::Tickets->new($session{'CurrentUser'});
+$Tickets->FromSQL($ARGS{'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);
+}
+$r->content_type('application/rss+xml');
+
+
+
+ # create an RSS 1.0 file (http://purl.org/rss/1.0/)
+ use XML::RSS;
+ my $rss = new XML::RSS (version => '1.0');
+ $rss->channel(
+ title => RT->Config->Get('rtname').": Search " . $ARGS{'Query'},
+ link => RT->Config->Get('WebURL'),
+ description => "",
+ dc => {
+ },
+ generator => "RT v" . $RT::VERSION,
+ syn => {
+ updatePeriod => "hourly",
+ updateFrequency => "1",
+ updateBase => "1901-01-01T00:00+00:00",
+ },
+ );
+
+
+ while ( my $Ticket = $Tickets->Next()) {
+ my $creator_str = $m->scomp('/Elements/ShowUser', User => $Ticket->CreatorObj);
+ $creator_str =~ s/[\r\n]//g;
+ $rss->add_item(
+ title => $Ticket->Subject || loc('No Subject'),
+ link => RT->Config->Get('WebURL')."Ticket/Display.html?id=".$Ticket->id,
+ description => $Ticket->Transactions->First->Content,
+ dc => { creator => $creator_str,
+ date => $Ticket->CreatedObj->RFC2822,
+ },
+ guid => $Ticket->Queue . '_' . $Ticket->id,
+ );
+ }
+
+$m->out($rss->as_string);
+$session{'CurrentUser'} = $old_current_user if $old_current_user;
+$m->abort();
+</%INIT>
+<%ARGS>
+$OrderBy => 'Created'
+$Order => 'ASC'
+</%ARGS>
+
diff --git a/rt/share/html/Search/Results.html b/rt/share/html/Search/Results.html
index 13252eebb..22858f172 100755
--- a/rt/share/html/Search/Results.html
+++ b/rt/share/html/Search/Results.html
@@ -84,6 +84,7 @@
</div>
<div align="right" class="search-result-actions">
<& Elements/ResultViews,
+ Collection => $session{'tickets'},
QueryString => $QueryString,
Query => $Query,
Format => $Format,
@@ -118,6 +119,7 @@ if ( !defined($Rows) ) {
$Rows = 50;
}
}
+$Page = 1 unless $Page && $Page > 0;
my ($title, $ticketcount);
$session{'i'}++;
@@ -134,6 +136,8 @@ if ($OrderBy =~ /\|/) {
} else {
$session{'tickets'}->OrderBy(FIELD => $OrderBy, ORDER => $Order);
}
+$session{'tickets'}->RowsPerPage( $Rows ) if $Rows;
+$session{'tickets'}->GotoPage( $Page - 1 );
$session{'CurrentSearchHash'} = {
Format => $Format,
@@ -142,7 +146,7 @@ $session{'CurrentSearchHash'} = {
Order => $Order,
OrderBy => $OrderBy,
RowsPerPage => $Rows
- };
+};
if ( $session{'tickets'}->Query()) {
@@ -161,7 +165,10 @@ my $QueryString = "?".$m->comp('/Elements/QueryString',
Page => $Page);
my $ShortQueryString = "?".$m->comp('/Elements/QueryString', Query => $Query);
my $RSSQueryString = "?".$m->comp('/Elements/QueryString', Query => $Query, Order => $Order, OrderBy => $OrderBy);
-my $RSSFeedURL = RT->Config->Get('WebPath')."/Search/Results.rdf$RSSQueryString";
+my $RSSPath = join '/', map $m->interp->apply_escapes($_, 'u'),
+ $session{'CurrentUser'}->UserObj->Name,
+ $session{'CurrentUser'}->UserObj->GenerateAuthString( $Query.$Order.$OrderBy );
+my $RSSFeedURL = RT->Config->Get('WebPath')."/NoAuth/rss/$RSSPath/$RSSQueryString";
if ($ARGS{'TicketsRefreshInterval'}) {
$session{'tickets_refresh_interval'} = $ARGS{'TicketsRefreshInterval'};
diff --git a/rt/share/html/Search/Results.rdf b/rt/share/html/Search/Results.rdf
index 0a1943059..c402b6f8e 100644
--- a/rt/share/html/Search/Results.rdf
+++ b/rt/share/html/Search/Results.rdf
@@ -45,59 +45,4 @@
%# those contributions and any derivatives thereof.
%#
%# END BPS TAGGED BLOCK }}}
-<%INIT>
-
-my $Tickets = RT::Tickets->new($session{'CurrentUser'});
-$Tickets->FromSQL($ARGS{'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);
-}
-$r->content_type('application/rss+xml');
-
-
-
- # create an RSS 1.0 file (http://purl.org/rss/1.0/)
- use XML::RSS;
- my $rss = new XML::RSS (version => '1.0');
- $rss->channel(
- title => RT->Config->Get('rtname').": Search" . $ARGS{'Query'},
- link => RT->Config->Get('WebURL'),
- description => "",
- dc => {
- },
- generator => "RT v" . $RT::VERSION,
- syn => {
- updatePeriod => "hourly",
- updateFrequency => "1",
- updateBase => "1901-01-01T00:00+00:00",
- },
- );
-
-
- while ( my $Ticket = $Tickets->Next()) {
- my $creator_str = $m->scomp('/Elements/ShowUser', User => $Ticket->CreatorObj);
- $creator_str =~ s/[\r\n]//g;
- $rss->add_item(
- title => $Ticket->Subject || loc('No Subject'),
- link => RT->Config->Get('WebURL')."Ticket/Display.html?id=".$Ticket->id,
- description => $Ticket->Transactions->First->Content,
- dc => { creator => $creator_str,
- date => $Ticket->CreatedObj->RFC2822,
- },
- guid => $Ticket->Queue . '_' . $Ticket->id,
- );
- }
-$m->out($rss->as_string);
-$m->abort();
-</%INIT>
-<%ARGS>
-$OrderBy => 'Created'
-$Order => 'ASC'
-</%ARGS>
+<& /Search/Elements/ResultsRSSView, %ARGS &>
diff --git a/rt/share/html/Search/Results.tsv b/rt/share/html/Search/Results.tsv
index bb3ac4482..946a35d02 100644
--- a/rt/share/html/Search/Results.tsv
+++ b/rt/share/html/Search/Results.tsv
@@ -107,7 +107,7 @@ $r->content_type('application/vnd.ms-excel');
$_ += @header - 1 foreach values %cf_name_to_pos;
- foreach my $name ( sort { $cf_name_to_pos{$a} <=> $cf_name_to_pos{$a} } keys %cf_name_to_pos ) {
+ foreach my $name ( sort { $cf_name_to_pos{$a} <=> $cf_name_to_pos{$b} } keys %cf_name_to_pos ) {
push @header, "CF-". $name;
}
$m->out(join("\t", @header));
diff --git a/rt/share/html/SelfService/Error.html b/rt/share/html/SelfService/Error.html
index 9c81ebbe6..8956c3ea1 100755
--- a/rt/share/html/SelfService/Error.html
+++ b/rt/share/html/SelfService/Error.html
@@ -66,6 +66,6 @@ $Why => loc("the calling component did not specify why")
</%args>
<%INIT>
-$Details ||= "No details";
+$Details ||= loc("No details");
$RT::Logger->error("WebRT: $Why ($Details)");
</%INIT>
diff --git a/rt/share/html/SelfService/Prefs.html b/rt/share/html/SelfService/Prefs.html
index dabab7937..468a3d508 100755
--- a/rt/share/html/SelfService/Prefs.html
+++ b/rt/share/html/SelfService/Prefs.html
@@ -50,13 +50,14 @@
<& /Elements/ListActions, actions => \@results &>
<form method="post">
-% unless (RT->Config->Get('WebExternalAuth') and !RT->Config->Get('WebFallbackToInternalAuth')) {
<&| /Widgets/TitleBox, title => loc('Change password') &>
-<&|/l&>New password</&>: <input type="password" name="NewPass1" size="16" autocomplete="off" />
-<&|/l&>Confirm</&>: <input type="password" name="NewPass2" size="16" autocomplete="off" />
+<& /Elements/EditPassword,
+ User => $user,
+ Name => [qw(CurrentPass NewPass1 NewPass2)],
+&>
</&>
+
<br />
-% }
<& /Elements/Submit, Label => loc('Save Changes') &>
</form>
@@ -64,29 +65,32 @@
<%INIT>
my @results;
-if ($NewPass1) {
- if ($NewPass1 ne $NewPass2) {
- push (@results, "Passwords did not match.");
- }
- else {
- my ($val, $msg)=$session{'CurrentUser'}->UserObj->SetPassword($NewPass1);
- push (@results, "Password: ".$msg);
- }
+my $user = $session{'CurrentUser'}->UserObj;
+
+if (defined $NewPass1 && length $NewPass1 ) {
+ my ($status, $msg) = $user->SafeSetPassword(
+ Current => $CurrentPass,
+ New => $NewPass1,
+ Confirmation => $NewPass2,
+ );
+ push @results, loc("Password: [_1]", $msg);
}
+
if ($Signature) {
$Signature =~ s/(\r\n|\r)/\n/g;
- if ($Signature ne $session{'CurrentUser'}->UserObj->Signature) {
- my ($val, $msg)=$session{'CurrentUser'}->UserObj->SetSignature($Signature);
+ if ($Signature ne $user->Signature) {
+ my ($val, $msg) = $user->SetSignature($Signature);
push (@results, "Signature: ".$msg);
}
}
-#A hack to make sure that session gets rewritten.
+#A hack to make sure that session gets rewritten.
$session{'i'}++;
</%INIT>
<%ARGS>
$Signature => undef
+$CurrentPass => undef
$NewPass1 => undef
$NewPass2 => undef
</%ARGS>
diff --git a/rt/share/html/Ticket/Attachment/dhandler b/rt/share/html/Ticket/Attachment/dhandler
index d4d556b24..8b41329ba 100755
--- a/rt/share/html/Ticket/Attachment/dhandler
+++ b/rt/share/html/Ticket/Attachment/dhandler
@@ -68,8 +68,11 @@
}
my $content_type = $AttachmentObj->ContentType || 'text/plain';
-
- unless (RT->Config->Get('TrustHTMLAttachments')) {
+
+ if (RT->Config->Get('AlwaysDownloadAttachments')) {
+ $r->headers_out->{'Content-Disposition'} = "attachment; filename=" . $AttachmentObj->Filename;
+ }
+ elsif (!RT->Config->Get('TrustHTMLAttachments')) {
$content_type = 'text/plain' if ($content_type =~ /^text\/html/i);
}
diff --git a/rt/share/html/Ticket/Create.html b/rt/share/html/Ticket/Create.html
index 28b655691..2c8e35778 100755
--- a/rt/share/html/Ticket/Create.html
+++ b/rt/share/html/Ticket/Create.html
@@ -112,6 +112,7 @@
</td>
<td class="value" colspan="5">
<input name="Subject" size="60" maxsize="200" value="<%$ARGS{Subject} || ''%>" />
+% $m->callback( %ARGS, CallbackName => 'AfterSubject' );
</td>
</tr>
<tr>
@@ -158,6 +159,7 @@
% } else {
<& /Elements/MessageBox, QuoteTransaction => $QuoteTransaction &>
%}
+% $m->callback( %ARGS, QueueObj => $QueueObj, CallbackName => 'AfterMessageBox' );
<br />
</td>
@@ -392,6 +394,22 @@ if ( !exists $ARGS{'AddMoreAttach'} && ($ARGS{'id'}||'') eq 'new' ) {
$checks_failure = 1 unless $status;
}
+# check email addresses for RT's
+{
+ foreach my $field ( qw(Requestors Cc AdminCc) ) {
+ my $value = $ARGS{ $field };
+ next unless defined $value && length $value;
+
+ my @emails = Email::Address->parse( $value );
+ foreach my $email ( grep RT::EmailParser->IsRTAddress($_->address), @emails ) {
+ push @results, loc("[_1] is an address RT receives mail at. Adding it as a '[_2]' would create a mail loop", $email->format, loc($field =~ /^(.*?)s?$/) );
+ $checks_failure = 1;
+ $email = undef;
+ }
+ $ARGS{ $field } = join ', ', map $_->format, grep defined, @emails;
+ }
+}
+
my $skip_create = 0;
$m->callback( CallbackName => 'BeforeCreate', ARGSRef => \%ARGS, skip_create => \$skip_create,
checks_failure => $checks_failure, results => \@results );
diff --git a/rt/share/html/Ticket/Elements/EditCustomFields b/rt/share/html/Ticket/Elements/EditCustomFields
index c3a44ee22..5478c7871 100755
--- a/rt/share/html/Ticket/Elements/EditCustomFields
+++ b/rt/share/html/Ticket/Elements/EditCustomFields
@@ -45,6 +45,7 @@
%# those contributions and any derivatives thereof.
%#
%# END BPS TAGGED BLOCK }}}
+% $m->callback( %ARGS, CallbackName => 'BeforeCustomFields' );
<table>
% my $i = 0;
% while ( my $CustomField = $CustomFields->Next ) {
@@ -85,6 +86,7 @@
% }
</table>
+% $m->callback( %ARGS, CallbackName => 'AfterCustomFields', TicketObj => $TicketObj, QueueObj => $QueueObj );
<%INIT>
my $CustomFields;
diff --git a/rt/share/html/Ticket/Elements/EditDates b/rt/share/html/Ticket/Elements/EditDates
index fc17cdbd4..e6f724f7b 100755
--- a/rt/share/html/Ticket/Elements/EditDates
+++ b/rt/share/html/Ticket/Elements/EditDates
@@ -70,6 +70,7 @@
<& /Elements/SelectDate, menu_prefix => 'Due', current => 0 &> (<% $TicketObj->DueObj->AsString %>)
</td>
</tr>
+% $m->callback( %ARGS, CallbackName => 'EndOfList', Ticket => $TicketObj );
</table>
<%ARGS>
$TicketObj => undef
diff --git a/rt/share/html/Ticket/Elements/EditTransactionCustomFields b/rt/share/html/Ticket/Elements/EditTransactionCustomFields
index 8bf939db6..a58dded9b 100644
--- a/rt/share/html/Ticket/Elements/EditTransactionCustomFields
+++ b/rt/share/html/Ticket/Elements/EditTransactionCustomFields
@@ -45,6 +45,7 @@
%# those contributions and any derivatives thereof.
%#
%# END BPS TAGGED BLOCK }}}
+% $m->callback( CallbackName => 'BeforeTransactionCustomFields', TicketObj => $TicketObj, QueueObj => $QueueObj, NamePrefix => $NamePrefix );
% if ($CustomFields->Count) {
% while (my $CF = $CustomFields->Next()) {
% next unless $CF->CurrentUserHasRight('ModifyCustomField');
@@ -60,6 +61,7 @@
</td></tr>
% }
% }
+% $m->callback( CallbackName => 'AfterTransactionCustomFields', TicketObj => $TicketObj, QueueObj => $QueueObj, NamePrefix => $NamePrefix );
<%INIT>
my $CustomFields;
diff --git a/rt/share/html/Ticket/Elements/PreviewScrips b/rt/share/html/Ticket/Elements/PreviewScrips
index 7480adecf..d376f5d08 100755
--- a/rt/share/html/Ticket/Elements/PreviewScrips
+++ b/rt/share/html/Ticket/Elements/PreviewScrips
@@ -69,7 +69,11 @@ my @non_recipients = @{ $squelch{'EmailAddresses'} };
%my @addresses = $scrip->ActionObj->Action->$type();
<ul>
%foreach my $addr (@addresses) {
-<li> <b><%loc($type)%></b>: <input type="checkbox" class="checkbox" name="Ticket-<%$TicketObj->id%>-SquelchMailTo" value="<%$addr->address%>" /> <%$addr->address%>
+<li>
+ <b><%loc($type)%></b>: <input type="checkbox" class="checkbox" name="Ticket-<%$TicketObj->id%>-SquelchMailTo" value="<%$addr->address%>" /> <%$addr->address%>
+
+% $m->callback(CallbackName => 'AfterAddress', Ticket => $TicketObj, Address => $addr, Type => $type);
+</li>
% }
</ul>
% }
diff --git a/rt/share/html/Ticket/Elements/ShowAttachments b/rt/share/html/Ticket/Elements/ShowAttachments
index 72298d79f..ab0d92112 100755
--- a/rt/share/html/Ticket/Elements/ShowAttachments
+++ b/rt/share/html/Ticket/Elements/ShowAttachments
@@ -61,11 +61,22 @@
my $size = $rev->ContentLength;
if ($size) {
- if ($size > 1024) {
- $size = int($size/102.4)/10 . "k";
+ my $kb = int($size/102.4) / 10;
+ my $units = RT->Config->Get('AttachmentUnits');
+
+ if (!defined($units)) {
+ if ($size > 1024) {
+ $size = $kb . "k";
+ }
+ else {
+ $size = $size . "b";
+ }
+ }
+ elsif ($units eq 'k') {
+ $size = $kb . "k";
}
else {
- $size = $size ."b";
+ $size = $size . "b";
}
</%PERL>
diff --git a/rt/share/html/Ticket/Elements/ShowDates b/rt/share/html/Ticket/Elements/ShowDates
index d309907dc..07140c2e4 100755
--- a/rt/share/html/Ticket/Elements/ShowDates
+++ b/rt/share/html/Ticket/Elements/ShowDates
@@ -84,6 +84,7 @@
<td class="value date updated"><% $UpdatedString | h %></td>
% }
</tr>
+% $m->callback( %ARGS, CallbackName => 'EndOfList', TicketObj => $Ticket );
</table>
<%ARGS>
$Ticket => undef
diff --git a/rt/share/html/Ticket/Elements/ShowGroupMembers b/rt/share/html/Ticket/Elements/ShowGroupMembers
index a15f850b4..6597cc543 100644
--- a/rt/share/html/Ticket/Elements/ShowGroupMembers
+++ b/rt/share/html/Ticket/Elements/ShowGroupMembers
@@ -50,7 +50,9 @@
% my $Users = $Group->UserMembersObj( Recursively => $Recursively );
% while ( my $user = $Users->Next ) {
<& /Elements/ShowUser, User => $user, Ticket => $Ticket &>
-<& /Elements/ShowUserEmailFrequency, User => $user, Ticket => $Ticket &><br />
+<& /Elements/ShowUserEmailFrequency, User => $user, Ticket => $Ticket &>
+% $m->callback( User => $user, Ticket => $Ticket, %ARGS, CallbackName => 'AboutThisUser' );
+<br />
% }
% my $Groups = $Group->GroupMembersObj( Recursively => $Recursively );
% $Groups->LimitToUserDefinedGroups;
diff --git a/rt/share/html/Ticket/Elements/ShowMessageStanza b/rt/share/html/Ticket/Elements/ShowMessageStanza
index 0d4fe6154..9d2f21120 100755
--- a/rt/share/html/Ticket/Elements/ShowMessageStanza
+++ b/rt/share/html/Ticket/Elements/ShowMessageStanza
@@ -48,7 +48,8 @@
<%perl>
if ( ref $Message ) {
$m->out('<pre>') if $plain_text_pre && !$Depth && !$plain_text_mono;
- $m->out( qq{<div class="message-stanza-depth-$Depth">} );
+ $m->out( qq{<div class="message-stanza-depth-$Depth } .($plain_text_mono ? "plain-text-white-space" : "") .qq{">} );
+
my @stack;
my $para = '';
diff --git a/rt/share/html/Ticket/Elements/ShowPeople b/rt/share/html/Ticket/Elements/ShowPeople
index ddd2e3c6f..1f0e5319e 100755
--- a/rt/share/html/Ticket/Elements/ShowPeople
+++ b/rt/share/html/Ticket/Elements/ShowPeople
@@ -50,7 +50,9 @@
<td class="label"><&|/l&>Owner</&>:</td>
% my $owner = $Ticket->OwnerObj;
<td class="value"><& /Elements/ShowUser, User => $owner, Ticket => $Ticket &>
- <& /Elements/ShowUserEmailFrequency, User => $owner, Ticket => $Ticket &></td>
+ <& /Elements/ShowUserEmailFrequency, User => $owner, Ticket => $Ticket &>
+% $m->callback( User => $owner, Ticket => $Ticket, %ARGS, CallbackName => 'AboutThisUser' );
+ </td>
</tr>
<tr>
<td class="labeltop"><&|/l&>Requestors</&>:</td>
diff --git a/rt/share/html/Ticket/Elements/ShowTransaction b/rt/share/html/Ticket/Elements/ShowTransaction
index a533323a9..6ccbb0c89 100755
--- a/rt/share/html/Ticket/Elements/ShowTransaction
+++ b/rt/share/html/Ticket/Elements/ShowTransaction
@@ -55,11 +55,13 @@
<a name="txn-<% $Transaction->Id %>" href="<% $DisplayPath %>#txn-<% $Transaction->Id %>">#</a>
<% $LastTransaction ? '<a id="lasttrans" name="lasttrans"></a>' : ''|n %>
</span>
+% $m->callback( Transaction => $Transaction, %ARGS, CallbackName => 'AfterAnchor' );
<span class="date"><% $transdate|n %></span>
% my $desc = $Transaction->BriefDescription;
% $m->callback( text => \$desc, Transaction => $Transaction, %ARGS, CallbackName => 'ModifyDisplay' );
<span class="description">
<& /Elements/ShowUser, User => $Transaction->CreatorObj &> - <% $TicketString %> <% $desc %>
+% $m->callback( Transaction => $Transaction, %ARGS, CallbackName => 'AfterDescription' );
</span>
% $m->callback( TimeTaken => \$TimeTaken, Transaction => $Transaction, %ARGS, CallbackName => 'ModifyTimeTaken' );
<span class="time-taken"><% $TimeTaken %></span>
diff --git a/rt/share/html/Ticket/Elements/UpdateCc b/rt/share/html/Ticket/Elements/UpdateCc
index 2538c82df..2559e5652 100644
--- a/rt/share/html/Ticket/Elements/UpdateCc
+++ b/rt/share/html/Ticket/Elements/UpdateCc
@@ -49,24 +49,32 @@
<input type="hidden" id="UpdateIgnoreAddressCheckboxes" name="UpdateIgnoreAddressCheckboxes" value="0">
<br />
-%foreach my $addr ( keys %txn_addresses) {
-% next if ( grep {$addr eq $_} @req_addresses );
+%if (scalar @one_time_Ccs) {
+<i class="label">(<&|/l&>check to add</&>)</i>
+%}
+%foreach my $addr ( @one_time_Ccs ) {
<input
id="UpdateCc-<%$addr%>"
name="UpdateCc-<%$addr%>"
type="checkbox"
- onClick="checkboxToInput('UpdateCc', 'UpdateCc-<%$addr%>','<%$txn_addresses{$addr}->format%>' ); $(UpdateIgnoreAddressCheckboxes).value=1"
+% my $clean_addr = $txn_addresses{$addr}->format;
+% $clean_addr =~ s/'/\\'/g;
+ onClick="checkboxToInput('UpdateCc', 'UpdateCc-<%$addr%>','<%$clean_addr%>' ); $(UpdateIgnoreAddressCheckboxes).value=1"
<% $ARGS{'UpdateCc-'.$addr} ? 'checked="checked"' : ''%> > <& /Elements/ShowUser, Address => $txn_addresses{$addr}&>
%}
</td></tr>
<tr><td class="label"><&|/l&>One-time Bcc</&>:</td><td><& /Elements/EmailInput, Name => 'UpdateBcc', Size => '60', Default => $ARGS{UpdateBcc} &><br />
-%foreach my $addr ( keys %txn_addresses) {
-% next if ( grep {$addr eq $_} @req_addresses );
+%if (scalar @one_time_Ccs) {
+<i class="label">(<&|/l&>check to add</&>)</i>
+%}
+%foreach my $addr ( @one_time_Ccs ) {
<input
id="UpdateBcc-<%$addr%>"
name="UpdateBcc-<%$addr%>"
type="checkbox"
- onClick="checkboxToInput('UpdateBcc', 'UpdateBcc-<%$addr%>','<%$txn_addresses{$addr}->format%>' ); $(UpdateIgnoreAddressCheckboxes).value=1"
+% my $clean_addr = $txn_addresses{$addr}->format;
+% $clean_addr =~ s/'/\\'/g;
+ onClick="checkboxToInput('UpdateBcc', 'UpdateBcc-<%$addr%>','<%$clean_addr%>' ); $(UpdateIgnoreAddressCheckboxes).value=1"
<% $ARGS{'UpdateBcc-'.$addr} ? 'checked="checked"' : ''%>>
<& /Elements/ShowUser, Address => $txn_addresses{$addr}&>
%}
@@ -77,4 +85,10 @@ $TicketObj
<%init>
my %txn_addresses = %{$TicketObj->TransactionAddresses};
my @req_addresses = split /,/, $TicketObj->RequestorAddresses;
+my @one_time_Ccs;
+
+foreach my $addr ( keys %txn_addresses) {
+ next if ( grep {$addr eq $_} @req_addresses );
+ push @one_time_Ccs,$addr;
+}
</%init>
diff --git a/rt/share/html/Ticket/ModifyAll.html b/rt/share/html/Ticket/ModifyAll.html
index 762870099..41eda1b97 100755
--- a/rt/share/html/Ticket/ModifyAll.html
+++ b/rt/share/html/Ticket/ModifyAll.html
@@ -97,6 +97,7 @@
<option value="response"><&|/l&>Reply to requestors</&></option>
% }
</select>
+% $m->callback( %ARGS, CallbackName => 'AfterUpdateType' );
</td>
</tr>
<tr>
@@ -133,8 +134,13 @@
</tr>
<tr>
<td class="labeltop"><&|/l&>Content</&>:</td>
- <td class="entry"><& /Elements/MessageBox, Name=>"UpdateContent", QuoteTransaction=>$ARGS{QuoteTransaction} &></td>
- </tr>
+ <td class="entry">
+% if (exists $ARGS{UpdateContent}) {
+ <& /Elements/MessageBox, Name=>"UpdateContent", Default=>$ARGS{UpdateContent}, IncludeSignature => 0 &>
+% } else {
+ <& /Elements/MessageBox, Name=>"UpdateContent", QuoteTransaction=>$ARGS{QuoteTransaction} &>
+% }
+ </td></tr>
</table>
</&>
diff --git a/rt/share/html/Ticket/ModifyDates.html b/rt/share/html/Ticket/ModifyDates.html
index 69bfde8ef..22bac10cb 100755
--- a/rt/share/html/Ticket/ModifyDates.html
+++ b/rt/share/html/Ticket/ModifyDates.html
@@ -69,6 +69,7 @@
my $TicketObj = LoadTicket($id);
$m->callback( TicketObj => $TicketObj, ARGSRef => \%ARGS );
my @results = ProcessTicketDates( TicketObj => $TicketObj, ARGSRef => \%ARGS);
+push @results, ProcessObjectCustomFieldUpdates(Object => $TicketObj, ARGSRef => \%ARGS);
$TicketObj->ApplyTransactionBatch;
</%INIT>
diff --git a/rt/share/html/Ticket/Update.html b/rt/share/html/Ticket/Update.html
index d3c2a09c4..f5cdddea8 100755
--- a/rt/share/html/Ticket/Update.html
+++ b/rt/share/html/Ticket/Update.html
@@ -55,7 +55,7 @@
<form action="Update.html" name="TicketUpdate"
method="post" enctype="multipart/form-data">
-% $m->callback( CallbackName => 'FormStart', ARGSRef => \%ARGS, Ticket => $TicketObj );
+% $m->callback( CallbackName => 'FormStart', ARGSRef => \%ARGS, Ticket => $TicketObj, CanRespond => $CanRespond, CanComment => $CanComment, ResponseDefault => $ResponseDefault, CommentDefault => $CommentDefault );
<input type="hidden" class="hidden" name="QuoteTransaction" value="<% $ARGS{QuoteTransaction}||'' %>" />
<input type="hidden" class="hidden" name="DefaultStatus" value="<% $DefaultStatus ||''%>" />
<input type="hidden" class="hidden" name="Action" value="<% $ARGS{Action}||'' %>" />
@@ -97,8 +97,11 @@
<option value="response" <% ($ARGS{'UpdateType'} && $ARGS{'UpdateType'} eq "response") ? qq[ selected="selected"] : !$ARGS{'UpdateType'}&&$ResponseDefault |n %>><&|/l&>Reply to requestors</&></option>
% }
</select>
+% $m->callback( %ARGS, CallbackName => 'AfterUpdateType' );
+</td></tr>
+<tr><td class="label"><&|/l&>Subject</&>:</td><td> <input name="UpdateSubject" size="60" value="<% $ARGS{UpdateSubject} || $TicketObj->Subject()%>" />
+% $m->callback( %ARGS, CallbackName => 'AfterSubject' );
</td></tr>
-<tr><td class="label"><&|/l&>Subject</&>:</td><td> <input name="UpdateSubject" size="60" value="<% $ARGS{UpdateSubject} || $TicketObj->Subject()%>" /></td></tr>
<& /Ticket/Elements/UpdateCc, %ARGS, TicketObj => $TicketObj &>
@@ -126,6 +129,7 @@
&>
</td></tr>
% }
+% $m->callback( %ARGS, CallbackName => 'AfterGnuPG' );
<tr><td class="label" valign="top"><&|/l&>Message</&>:</td><td>
% $m->callback( %ARGS, CallbackName => 'BeforeMessageBox' );
@@ -136,7 +140,9 @@
<& /Elements/MessageBox, Name=>"UpdateContent", Default=>$ARGS{UpdateContent}, IncludeSignature => 0, %ARGS&>
% $ARGS{'QuoteTransaction'} = $temp;
% } else {
-<& /Elements/MessageBox, Name=>"UpdateContent", %ARGS &>
+% my $IncludeSignature = 1;
+% $IncludeSignature = 0 if $Action ne 'Respond' && !RT->Config->Get('MessageBoxIncludeSignatureOnComment');
+<& /Elements/MessageBox, Name=>"UpdateContent", IncludeSignature => $IncludeSignature, %ARGS &>
% }
</td></tr>
</table>
@@ -256,6 +262,22 @@ if ( $ARGS{'SubmitTicket'} ) {
$checks_failure = 1 unless $status;
}
+# check email addresses for RT's
+{
+ foreach my $field ( qw(UpdateCc UpdateBcc) ) {
+ my $value = $ARGS{ $field };
+ next unless defined $value && length $value;
+
+ my @emails = Email::Address->parse( $value );
+ foreach my $email ( grep RT::EmailParser->IsRTAddress($_->address), @emails ) {
+ push @results, loc("[_1] is an address RT receives mail at. Adding it as a '[_2]' would create a mail loop", $email->format, loc(substr($field, 6)) );
+ $checks_failure = 1;
+ $email = undef;
+ }
+ $ARGS{ $field } = join ', ', map $_->format, grep defined, @emails;
+ }
+}
+
if ( !$checks_failure && exists $ARGS{SubmitTicket} ) {
$m->callback( Ticket => $TicketObj, ARGSRef => \%ARGS, CallbackName => 'BeforeDisplay' );
return $m->comp('Display.html', TicketObj => $TicketObj, %ARGS);
diff --git a/rt/share/html/Tools/Reports/CreatedByDates.html b/rt/share/html/Tools/Reports/CreatedByDates.html
index 9ca69557e..ce075970b 100644
--- a/rt/share/html/Tools/Reports/CreatedByDates.html
+++ b/rt/share/html/Tools/Reports/CreatedByDates.html
@@ -76,8 +76,8 @@ $q->LoadByCols(Name => $Queue);
% if ($Queue|| $CreatedBefore ||$CreatedAfter) {
% # if we have a queue, do the search
% if ($Queue) { $query .= " AND Queue = '$Queue'"}
-% if ($CreatedBefore) { $query .= " AND Created < '".$before->ISO."'"; }
-% if ($CreatedAfter) { $query .= " AND Created > '".$after->ISO."'"}
+% if ($CreatedBefore) { $query .= " AND Created < '".$before->ISO(Timezone => 'user') ."'"; }
+% if ($CreatedAfter) { $query .= " AND Created > '".$after->ISO(Timezone => 'user')."'"}
% my $groupby = 'Status';
<& /Search/Elements/Chart, Query => $query, PrimaryGroupBy => $groupby &>
% }
@@ -86,9 +86,9 @@ $q->LoadByCols(Name => $Queue);
<br /><&|/l&>Queue</&>: <& /Elements/SelectQueue, Name => 'Queue', NamedValues => 1, Default => $q->id &>
<br /><&|/l&>Tickets created after</&>:
-<& /Elements/SelectDate, Name => 'CreatedAfter', Default => ($CreatedAfter) ? $after->ISO : ''&>
+<& /Elements/SelectDate, Name => 'CreatedAfter', Default => ($CreatedAfter) ? $after->ISO(Timezone => 'user') : ''&>
<br /><&|/l&>Tickets created before</&>:
-<& /Elements/SelectDate, Name => 'CreatedBefore', Default => ($CreatedBefore) ? $before->ISO : ''&>
+<& /Elements/SelectDate, Name => 'CreatedBefore', Default => ($CreatedBefore) ? $before->ISO(Timezone => 'user') : ''&>
<& /Elements/Submit&>
</form>
diff --git a/rt/share/html/Tools/Reports/ResolvedByDates.html b/rt/share/html/Tools/Reports/ResolvedByDates.html
index 455eaedd2..48a952682 100644
--- a/rt/share/html/Tools/Reports/ResolvedByDates.html
+++ b/rt/share/html/Tools/Reports/ResolvedByDates.html
@@ -77,8 +77,8 @@ $q->LoadByCols(Name => $Queue);
% # if we have a queue, do the search
% $query = "Status = 'resolved'";
% if ($Queue) { $query .= " AND Queue = '$Queue'"}
-% if ($ResolvedBefore) { $query .= " AND Resolved < '".$before->ISO."'"; }
-% if ($ResolvedAfter) { $query .= " AND Resolved > '".$after->ISO."'"}
+% if ($ResolvedBefore) { $query .= " AND Resolved < '".$before->ISO(Timezone => 'user')."'"; }
+% if ($ResolvedAfter) { $query .= " AND Resolved > '".$after->ISO(Timezone => 'user')."'"}
% my $groupby = 'Owner';
<& /Search/Elements/Chart, Query => $query, PrimaryGroupBy => $groupby &>
% }
@@ -87,9 +87,9 @@ $q->LoadByCols(Name => $Queue);
<br /><&|/l&>Queue</&>: <& /Elements/SelectQueue, Name => 'Queue', NamedValues => 1, Default => $q->id &>
<br /><&|/l&>Tickets resolved after</&>:
-<& /Elements/SelectDate, Name => 'ResolvedAfter', Default => ($ResolvedAfter) ? $after->ISO : ''&>
+<& /Elements/SelectDate, Name => 'ResolvedAfter', Default => ($ResolvedAfter) ? $after->ISO(Timezone => 'user') : ''&>
<br /><&|/l&>Tickets resolved before</&>:
-<& /Elements/SelectDate, Name => 'ResolvedBefore', Default => ($ResolvedBefore) ? $before->ISO : ''&>
+<& /Elements/SelectDate, Name => 'ResolvedBefore', Default => ($ResolvedBefore) ? $before->ISO(Timezone => 'user') : ''&>
<& /Elements/Submit&>
</form>
diff --git a/rt/share/html/User/Elements/Tabs b/rt/share/html/User/Elements/Tabs
index 48cf1808b..7f9aca4dd 100755
--- a/rt/share/html/User/Elements/Tabs
+++ b/rt/share/html/User/Elements/Tabs
@@ -52,41 +52,43 @@
Title => $Title &>
<%INIT>
- my $tabs = {
-
- a => { title => loc('Settings'),
- path => 'Prefs/Other.html',
- },
-
- b => { title => loc('About me'),
- path => 'User/Prefs.html',
- },
- g => { title => loc('Personal Groups'),
- path => 'User/Groups/',
- },
- h => { title => loc('Delegation'),
- path => 'User/Delegation.html',
- },
- f => { title => loc('Search options'),
- path => 'Prefs/SearchOptions.html',
- },
- r => { title => loc('RT at a glance'),
- path => 'Prefs/MyRT.html',
- },
- };
+my $tabs = {
+ a => {
+ title => loc('Settings'),
+ path => 'Prefs/Other.html',
+ },
+ b => {
+ title => loc('About me'),
+ path => 'User/Prefs.html',
+ },
+ g => {
+ title => loc('Personal Groups'),
+ path => 'User/Groups/',
+ },
+ h => {
+ title => loc('Delegation'),
+ path => 'User/Delegation.html',
+ },
+ f => {
+ title => loc('Search options'),
+ path => 'Prefs/SearchOptions.html',
+ },
+ r => {
+ title => loc('RT at a glance'),
+ path => 'Prefs/MyRT.html',
+ },
+};
- # Now let callbacks add their extra tabs
- $m->callback( %ARGS, tabs => $tabs );
-
- foreach my $tab (sort keys %{$tabs}) {
- if ($tabs->{$tab}->{'path'} eq $current_tab) {
- $tabs->{$tab}->{"subtabs"} = $subtabs;
- $tabs->{$tab}->{"current_subtab"} = $current_subtab;
- }
- }
-</%INIT>
+# Now let callbacks add their extra tabs
+$m->callback( %ARGS, tabs => $tabs );
+foreach my $tab (values %$tabs) {
+ next unless $tab->{'path'} eq $current_tab;
+ $tab->{"subtabs"} = $subtabs;
+ $tab->{"current_subtab"} = $current_subtab;
+}
+</%INIT>
<%ARGS>
$subtabs => undef
$current_tab => undef
diff --git a/rt/share/html/Widgets/Form/Select b/rt/share/html/Widgets/Form/Select
index e77861740..4587f1d58 100644
--- a/rt/share/html/Widgets/Form/Select
+++ b/rt/share/html/Widgets/Form/Select
@@ -117,7 +117,10 @@ if ( $ValuesCallback ) {
}
}
unless (defined $DefaultLabel ) {
- $DefaultLabel = loc('Use system default ([_1])', join ', ', map{ loc($ValuesLabel{$_} || $_) } @DefaultValue);
+ $DefaultLabel = loc('Use system default ([_1])',
+ join ', ', map loc($ValuesLabel{$_} || $_), grep defined,
+ @DefaultValue
+ );
}
</%INIT>
</%METHOD>