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
commite70abd21bab68b23488f7ef1ee2e693a3b365691 (patch)
tree75986ffa9ba6ab4f961f9033468a1344e1653408 /rt/share
parentb4b0c7e72d7eaee2fbfc7022022c9698323203dd (diff)
import rt 3.8.8
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/Modify.html52
-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/ShowSummary111
-rwxr-xr-xrt/share/html/Ticket/Elements/ShowTransaction2
-rw-r--r--rt/share/html/Ticket/Elements/ShowTransactionAttachments7
-rwxr-xr-xrt/share/html/Ticket/Elements/Tabs24
-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
-rwxr-xr-xrt/share/html/User/Prefs.html43
-rw-r--r--rt/share/html/Widgets/Form/Select5
94 files changed, 1561 insertions, 826 deletions
diff --git a/rt/share/fonts/Droid.README b/rt/share/fonts/Droid.README
new file mode 100644
index 0000000..3a9cfca
--- /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 0000000..458ba59
--- /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 0000000..38b5b1a
--- /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 20d79b2..06e3739 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 139b8eb..16fb593 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 89c6d0f..0767e4a 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 29ec71c..2bcf64d 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 df349e1..dce0390 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 0bd68c2..7d7d930 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 078f51b..17b760c 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 df97a68..c6ffe17 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 52e7b3b..c0131b1 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 eb48af1..22c846a 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 ea5dd25..cd8574d 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/Modify.html b/rt/share/html/Admin/Users/Modify.html
index aae38b1..6af7bf3 100755
--- a/rt/share/html/Admin/Users/Modify.html
+++ b/rt/share/html/Admin/Users/Modify.html
@@ -113,26 +113,11 @@
<input type="hidden" class="hidden" name="SetPrivileged" value="1" />
<input type="checkbox" class="checkbox" name="Privileged" value="1" <%$PrivilegedChecked||''%> /> <&|/l&>Let this user be granted rights</&><br />
-
-% unless (RT->Config->Get('WebExternalAuth') and !RT->Config->Get('WebFallbackToInternalAuth')) {
-<table>
-<tr>
-<td align="right">
-<&|/l&>New Password</&>:
-</td>
-<td align="left">
-<input type="password" name="Pass1" autocomplete="off" />
-</td>
-</tr>
-<tr><td align="right">
-<&|/l&>Retype Password</&>:
-</td>
-<td>
-<input type="password" name="Pass2" autocomplete="off" />
-</td>
-</tr>
-</table>
-% }
+
+<& /Elements/EditPassword,
+ User => $UserObj,
+ Name => [qw(CurrentPass Pass1 Pass2)],
+&>
</&>
% $m->callback( %ARGS, CallbackName => 'LeftColumnBottom', UserObj => $UserObj );
</td>
@@ -364,22 +349,20 @@ if ($UserObj->Id && $id ne 'new') {
# }}}
}
+
+my %password_cond = $UserObj->CurrentUserRequireToSetPassword;
if ( $UserObj->Id ) {
- my $password_not_set;
# Deal with Password field
- if ( !$Pass1 and !$Pass2 ) {
- $password_not_set = 1;
- } elsif ( $Pass1 ne $Pass2 ) {
- $password_not_set = 1;
- push @results, loc("Passwords do not match.");
- } elsif ( $Pass1 eq $Pass2 and !$UserObj->IsPassword($Pass1) ) {
- my ($code, $msg) = $UserObj->SetPassword($Pass1);
- push @results, loc_fuzzy($msg);
- $password_not_set = 1 unless $code;
+ my ($status, $msg) = $UserObj->SafeSetPassword(
+ Current => $CurrentPass,
+ New => $Pass1,
+ Confirmation => $Pass2,
+ );
+ push @results, $msg;
+
+ if ( $id eq 'new' && !$status ) {
+ push @results, loc("A password was not set, so user won't be able to login.");
}
- if ($id eq 'new' and $password_not_set) {
- push @results, loc("A password was not set, so user won't be able to login.");
- }
}
@@ -431,7 +414,8 @@ $City => undef
$State => undef
$Zip => undef
$Country => undef
+$CurrentPass => undef
$Pass1 => undef
-$Pass2=> undef
+$Pass2 => undef
$Create=> undef
</%ARGS>
diff --git a/rt/share/html/Admin/Users/index.html b/rt/share/html/Admin/Users/index.html
index e9a5818..88a775f 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 aa3a67e..753d2fe 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 1893b53..ba01a9d 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 218de33..d8c7039 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 fa7474b..a1af9f3 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 6f21420..c7bdfd9 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 71517e0..a1475a9 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 9c8f3aa..fd2ba9e 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 8fe79f9..30b06db 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 637762e..90acb46 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 0000000..3b0ec0b
--- /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 6ee88a1..c4eb175 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 8dfbe51..e768b0e 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 359738b..e6cb1ad 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 4985b23..854528c 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 25fdf5d..53e3f99 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 0000000..6d8d76a
--- /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 5c56004..f44ab32 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 88b4c4b..3e1d407 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 851cc9d..e7c1495 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 7df4710..c1f9e31 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 20a5b7d..c78afe9 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 ddb8b72..b60c49a 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 569bad3..e3b3ef5 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 0000000..3c1ed15
--- /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 2fbdcbc..01de725 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 3cdba10..c4cccca 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 96e8d77..70b43c1 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 5a4926b..7b80823 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 2a58b13..a7a445f 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 9b31b29..72b1a27 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 67b5e19..ca50203 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 329cf8f..f47b158 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 a92cfd1..f11f78a 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 0000000..84023eca
--- /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 aaa1e8a..ae50342 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 b98253a..a38854f 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 0f2f20c..fbd9af1 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 0000000..cbc8cef
--- /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 5ca5614..a477003 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 eef5f48..80d7ce0 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 184ac1d..2297c30 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 947f49d..d96d5a9 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 431a44f..7abf8b8 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 74028f8..e814154 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 0000000..c402b6f
--- /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 fa20e33..f2ca45c 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 59e9fc6..abee3e5 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 3db92c4..bf4cd0c 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 0000000..f335411
--- /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 13252ee..22858f1 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 0a19430..c402b6f 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 bb3ac44..946a35d 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 9c81ebb..8956c3e 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 dabab79..468a3d5 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 d4d556b..8b41329 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 28b6556..2c8e357 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 c3a44ee..5478c78 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 fc17cdb..e6f724f 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 8bf939d..a58dded 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 7480ade..d376f5d 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 72298d7..ab0d921 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 d309907..07140c2 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 a15f850..6597cc5 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 0d4fe61..9d2f211 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 ddd2e3c..1f0e531 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/ShowSummary b/rt/share/html/Ticket/Elements/ShowSummary
index 4c2d54e..21c53c5 100755
--- a/rt/share/html/Ticket/Elements/ShowSummary
+++ b/rt/share/html/Ticket/Elements/ShowSummary
@@ -45,73 +45,82 @@
%# those contributions and any derivatives thereof.
%#
%# END BPS TAGGED BLOCK }}}
- <table width="100%" class="ticket-summary">
- <tr>
- <td valign="top" class="boxcontainer">
- <&| /Widgets/TitleBox, title => loc('The Basics'),
- title_href => RT->Config->Get('WebPath')."/Ticket/Modify.html?id=".$Ticket->Id,
- class => 'ticket-info-basics' &>
- <& /Ticket/Elements/ShowBasics, Ticket => $Ticket &>
- </&>
+<table width="100%" class="ticket-summary">
+<tr>
+ <td valign="top" class="boxcontainer">
+% $m->callback( %ARGS, CallbackName => 'LeftColumnTop' );
+
+ <&| /Widgets/TitleBox, title => loc('The Basics'),
+ title_href => RT->Config->Get('WebPath')."/Ticket/Modify.html?id=".$Ticket->Id,
+ class => 'ticket-info-basics',
+ &>
+ <& /Ticket/Elements/ShowBasics, Ticket => $Ticket &>
+ </&>
% if ($Ticket->CustomFields->First) {
- <&| /Widgets/TitleBox, title => loc('Custom Fields'),
- title_href => RT->Config->Get('WebPath')."/Ticket/Modify.html?id=".$Ticket->Id,
- class => 'ticket-info-cfs' &>
- <& /Ticket/Elements/ShowCustomFields, Ticket => $Ticket &>
- </&>
+ <&| /Widgets/TitleBox, title => loc('Custom Fields'),
+ title_href => RT->Config->Get('WebPath')."/Ticket/Modify.html?id=".$Ticket->Id,
+ class => 'ticket-info-cfs',
+ &>
+ <& /Ticket/Elements/ShowCustomFields, Ticket => $Ticket &>
+ </&>
% }
- <&| /Widgets/TitleBox, title => loc('People'),
- title_href => RT->Config->Get('WebPath')."/Ticket/ModifyPeople.html?id=".$Ticket->Id,
- class => 'ticket-info-people' &>
- <& /Ticket/Elements/ShowPeople, Ticket => $Ticket &>
- </&>
- <& /Ticket/Elements/ShowAttachments, Ticket => $Ticket, Attachments => $Attachments &>
+ <&| /Widgets/TitleBox, title => loc('People'),
+ title_href => RT->Config->Get('WebPath')."/Ticket/ModifyPeople.html?id=".$Ticket->Id,
+ class => 'ticket-info-people',
+ &>
+ <& /Ticket/Elements/ShowPeople, Ticket => $Ticket &>
+ </&>
+
+ <& /Ticket/Elements/ShowAttachments, Ticket => $Ticket, Attachments => $Attachments &>
- <& /Ticket/Elements/ShowRequestor, Ticket => $Ticket &>
+ <& /Ticket/Elements/ShowRequestor, Ticket => $Ticket &>
% $m->callback( %ARGS, CallbackName => 'LeftColumn' );
- </td>
- <td valign="top" class="boxcontainer">
+
+ </td>
+ <td valign="top" class="boxcontainer">
+
+% $m->callback( %ARGS, CallbackName => 'RightColumnTop' );
+
% if ( RT->Config->Get('EnableReminders') ) {
- <&|/Widgets/TitleBox, title => loc("Reminders"),
- title_href => RT->Config->Get('WebPath')."/Ticket/Reminders.html?id=".$Ticket->Id,
- class => 'ticket-info-reminders' &>
- <table>
- <tr>
- <td>
+ <&|/Widgets/TitleBox, title => loc("Reminders"),
+ title_href => RT->Config->Get('WebPath')."/Ticket/Reminders.html?id=".$Ticket->Id,
+ class => 'ticket-info-reminders',
+ &>
+ <table><tr><td>
<form action="<%RT->Config->Get('WebPath')%>/Ticket/Display.html" method="post">
- <& /Ticket/Elements/Reminders, Ticket => $Ticket, ShowCompleted => 0 &>
- <div align="right"><input type="submit" class="button" value="<&|/l&>Save</&>" /></div>
+ <& /Ticket/Elements/Reminders, Ticket => $Ticket, ShowCompleted => 0 &>
+ <div align="right"><input type="submit" class="button" value="<&|/l&>Save</&>" /></div>
</form>
- </td>
- </tr>
- </table>
- </&>
+ </td></tr></table>
+ </&>
% }
- <&| /Widgets/TitleBox, title => loc("Dates"),
- title_href => RT->Config->Get('WebPath')."/Ticket/ModifyDates.html?id=".$Ticket->Id,
- class => 'ticket-info-dates' &>
- <& /Ticket/Elements/ShowDates, Ticket => $Ticket &>
- </&>
+
+ <&| /Widgets/TitleBox, title => loc("Dates"),
+ title_href => RT->Config->Get('WebPath')."/Ticket/ModifyDates.html?id=".$Ticket->Id,
+ class => 'ticket-info-dates',
+ &>
+ <& /Ticket/Elements/ShowDates, Ticket => $Ticket &>
+ </&>
+
% my (@extra);
% push @extra, titleright_raw => '<a href="'. RT->Config->Get('WebPath'). '/Ticket/Graphs/index.html?id='.$Ticket->id.'">'.loc('Graph').'</a>' unless RT->Config->Get('DisableGraphViz');
- <&| /Widgets/TitleBox, title => loc('Links'),
- title_href => RT->Config->Get('WebPath')."/Ticket/ModifyLinks.html?id=".$Ticket->Id,
- class => 'ticket-info-links', @extra &>
- <& /Elements/ShowLinks, Ticket => $Ticket &>
- </&>
+ <&| /Widgets/TitleBox, title => loc('Links'),
+ title_href => RT->Config->Get('WebPath')."/Ticket/ModifyLinks.html?id=".$Ticket->Id,
+ class => 'ticket-info-links',
+ @extra,
+ &>
+ <& /Elements/ShowLinks, Ticket => $Ticket &>
+ </&>
+
% $m->callback( %ARGS, CallbackName => 'RightColumn' );
- </td>
- </tr>
- </table>
+ </td>
+</tr>
+</table>
<%ARGS>
$Ticket => undef
$Attachments => undef
</%ARGS>
-
-
-
-
diff --git a/rt/share/html/Ticket/Elements/ShowTransaction b/rt/share/html/Ticket/Elements/ShowTransaction
index a533323..6ccbb0c 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/ShowTransactionAttachments b/rt/share/html/Ticket/Elements/ShowTransactionAttachments
index 9c40b28..a8cdfc1 100644
--- a/rt/share/html/Ticket/Elements/ShowTransactionAttachments
+++ b/rt/share/html/Ticket/Elements/ShowTransactionAttachments
@@ -67,7 +67,10 @@ foreach my $message ( grep $_->__Value('Parent') == $Parent, @$Attachments ) {
% if ( $DownloadableHeaders && !$message->Filename && $message->ContentType =~ /text/ ) {
/ <a href="<% $AttachPath %>/WithHeaders/<% $message->Id %>"><% loc('with headers') %></a>
% }
-<br />
+
+% $m->callback(CallbackName => 'AfterDownloadLinks', ARGSRef => \%ARGS, Ticket => $Ticket, Transaction => $Transaction, Attachment => $message);
+
+<br />
<span class="downloadcontenttype"><% $message->ContentType %> <% $size_to_str->( $size ) %></span>
</div>
% }
@@ -76,7 +79,7 @@ foreach my $message ( grep $_->__Value('Parent') == $Parent, @$Attachments ) {
% if ( scalar ( grep $_->__Value('Parent') == $message->id, @$Attachments ) ) {
<div class="messageattachments">
% } else {
-<div class="messagebody <% RT->Config->Get('PlainTextMono', $session{'CurrentUser'}) ? ' plain-text-white-space' : ''%>">
+<div class="messagebody">
% }
<%PERL>
diff --git a/rt/share/html/Ticket/Elements/Tabs b/rt/share/html/Ticket/Elements/Tabs
index 7deb8c1..a9e697a 100755
--- a/rt/share/html/Ticket/Elements/Tabs
+++ b/rt/share/html/Ticket/Elements/Tabs
@@ -75,11 +75,13 @@ if ($Ticket) {
# Don't display prev links if we're on the first ticket
if ( $item_map->{ $Ticket->Id }->{prev} ) {
- $searchtabs->{'_a'} = {
- class => "nav",
- path => "Ticket/Display.html?id=" . $item_map->{first},
- title => '<< ' . loc('First')
- };
+ if ( $item_map->{first} ) {
+ $searchtabs->{'_a'} = {
+ class => "nav",
+ path => "Ticket/Display.html?id=" . $item_map->{first},
+ title => '<< ' . loc('First')
+ };
+ }
$searchtabs->{"_b"} = {
class => "nav",
path => "Ticket/Display.html?id="
@@ -96,11 +98,13 @@ if ($Ticket) {
. $item_map->{ $Ticket->Id }->{next},
title => loc('Next') . ' >'
};
- $searchtabs->{'e'} = {
- class => "nav",
- path => "Ticket/Display.html?id=" . $item_map->{last},
- title => loc('Last') . ' >>'
- };
+ if ( $item_map->{last} ) {
+ $searchtabs->{'e'} = {
+ class => "nav",
+ path => "Ticket/Display.html?id=" . $item_map->{last},
+ title => loc('Last') . ' >>'
+ };
+ }
}
}
diff --git a/rt/share/html/Ticket/Elements/UpdateCc b/rt/share/html/Ticket/Elements/UpdateCc
index 2538c82..2559e56 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 7628700..41eda1b 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 69bfde8..22bac10 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 d3c2a09..f5cddde 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 9ca6955..ce07597 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 455eaed..48a9526 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 48cf180..7f9aca4 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/User/Prefs.html b/rt/share/html/User/Prefs.html
index f52fdcb..884cf85 100755
--- a/rt/share/html/User/Prefs.html
+++ b/rt/share/html/User/Prefs.html
@@ -107,27 +107,13 @@
% $m->callback( %ARGS, UserObj => $UserObj, CallbackName => 'FormLeftColumn' );
</td>
<td valign="top" class="boxcontainer">
-% unless (RT->Config->Get('WebExternalAuth') and !RT->Config->Get('WebFallbackToInternalAuth')) {
+
<&| /Widgets/TitleBox, title => loc('Password'), id => "user-prefs-password" &>
-<table>
-<tr>
-<td class="label">
-<&|/l&>New Password</&>:
-</td>
-<td class="value">
-<input type="password" name="Pass1" autocomplete="off"/>
-</td>
-</tr>
-<tr><td class="label">
-<&|/l&>Retype Password</&>:
-</td>
-<td class="value">
-<input type="password" name="Pass2" autocomplete="off" />
-</td>
-</tr>
-</table>
+<& /Elements/EditPassword,
+ User => $UserObj,
+ Name => [qw(CurrentPass Pass1 Pass2)],
+&>
</&>
-% }
<&| /Widgets/TitleBox, title => loc('Location'), id => "user-prefs-location" &>
<table cellspacing="0" cellpadding="0">
@@ -221,6 +207,7 @@ unless ( $UserObj->id ) {
if $Name;
Abort(loc("Couldn't load user"));
}
+$id = $UserObj->id;
my @results;
@@ -259,13 +246,14 @@ if ( $SetPrivileged and $Privileged != $UserObj->Privileged ) {
push @results, loc('Privileged status: [_1]', loc_fuzzy($msg));
}
-#TODO: make this report errors properly
-if ( defined $Pass1 and length $Pass1 and $Pass1 eq $Pass2 and !$UserObj->IsPassword($Pass1) ) {
- my ($code, $msg);
- ($code, $msg) = $UserObj->SetPassword($Pass1);
- push @results, loc('Password: [_1]', loc_fuzzy($msg));
-} elsif ( defined $Pass1 && length $Pass1 && $Pass1 ne $Pass2 ) {
- push @results, loc("Passwords do not match. Your password has not been changed");
+my %password_cond = $UserObj->CurrentUserRequireToSetPassword;
+if (defined $Pass1 && length $Pass1 ) {
+ my ($status, $msg) = $UserObj->SafeSetPassword(
+ Current => $CurrentPass,
+ New => $Pass1,
+ Confirmation => $Pass2,
+ );
+ push @results, loc("Password: [_1]", $msg);
}
if ( $ARGS{'ResetAuthToken'} ) {
@@ -308,7 +296,8 @@ $City => undef
$State => undef
$Zip => undef
$Country => undef
+$CurrentPass => undef
$Pass1 => undef
-$Pass2=> undef
+$Pass2 => undef
$Create=> undef
</%ARGS>
diff --git a/rt/share/html/Widgets/Form/Select b/rt/share/html/Widgets/Form/Select
index e778617..4587f1d 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>