From ed1f84b4e8f626245995ecda5afcf83092c153b2 Mon Sep 17 00:00:00 2001 From: Ivan Kohler Date: Mon, 15 Sep 2014 20:44:48 -0700 Subject: RT 4.0.22 --- rt/share/html/Admin/Users/Modify.html | 2 +- rt/share/html/Admin/Users/Modify.html.orig | 421 +++++++++++++++++++ rt/share/html/Approvals/index.html | 9 +- rt/share/html/Elements/.CalendarDaySchedule.swp | Bin 0 -> 12288 bytes rt/share/html/Elements/.CalendarEventWeekly.swp | Bin 0 -> 12288 bytes rt/share/html/Elements/.CalendarSlotSchedule.swp | Bin 0 -> 16384 bytes .../html/Elements/CalendarSlotSchedule.dynamic | 93 +++++ rt/share/html/Elements/EditCustomFieldDate | 3 +- rt/share/html/Elements/EditCustomFieldDateTime | 3 +- rt/share/html/Elements/Error | 6 +- rt/share/html/NoAuth/css/.calendar.css.swp | Bin 0 -> 12288 bytes rt/share/html/NoAuth/css/aileron/ticket.css | 16 - rt/share/html/NoAuth/css/base/ticket.css | 3 + rt/share/html/NoAuth/iCal/dhandler | 5 +- rt/share/html/NoAuth/images/week-collapse.xcf | Bin 0 -> 1996 bytes rt/share/html/NoAuth/images/week-expand.xcf | Bin 0 -> 1621 bytes rt/share/html/REST/1.0/Forms/ticket/comment | 5 +- rt/share/html/REST/1.0/Forms/ticket/default | 9 +- rt/share/html/REST/1.0/ticket/comment | 6 +- rt/share/html/Schedule/.UserBar.swp | Bin 0 -> 12288 bytes rt/share/html/Search/.Calendar.html.swp | Bin 0 -> 53248 bytes rt/share/html/Search/.Schedule.html.swp | Bin 0 -> 12288 bytes rt/share/html/Search/Bulk.html.orig | 460 ++++++++++++++++++++ rt/share/html/Search/Elements/ResultsRSSView | 6 +- rt/share/html/Search/Results.tsv | 4 +- rt/share/html/Search/Results.tsv.orig | 137 ++++++ rt/share/html/Ticket/Create.html | 4 +- rt/share/html/Ticket/Create.html.orig | 463 +++++++++++++++++++++ .../Ticket/Elements/EditTransactionCustomFields | 3 +- .../Elements/EditTransactionCustomFields.orig | 112 +++++ rt/share/html/Ticket/Elements/PreviewScrips | 2 +- rt/share/html/Ticket/Elements/ShowUpdateStatus | 2 +- rt/share/html/Ticket/Graphs/Elements/ShowGraph | 2 +- rt/share/html/Ticket/ModifyAll.html | 2 +- rt/share/html/Ticket/Update.html | 2 +- rt/share/html/Ticket/Update.html.orig | 353 ++++++++++++++++ rt/share/html/Tools/Offline.html | 1 - rt/share/html/Widgets/TitleBoxStart | 2 +- 38 files changed, 2080 insertions(+), 56 deletions(-) create mode 100755 rt/share/html/Admin/Users/Modify.html.orig create mode 100644 rt/share/html/Elements/.CalendarDaySchedule.swp create mode 100644 rt/share/html/Elements/.CalendarEventWeekly.swp create mode 100644 rt/share/html/Elements/.CalendarSlotSchedule.swp create mode 100644 rt/share/html/Elements/CalendarSlotSchedule.dynamic create mode 100644 rt/share/html/NoAuth/css/.calendar.css.swp create mode 100644 rt/share/html/NoAuth/images/week-collapse.xcf create mode 100644 rt/share/html/NoAuth/images/week-expand.xcf create mode 100644 rt/share/html/Schedule/.UserBar.swp create mode 100644 rt/share/html/Search/.Calendar.html.swp create mode 100644 rt/share/html/Search/.Schedule.html.swp create mode 100755 rt/share/html/Search/Bulk.html.orig create mode 100644 rt/share/html/Search/Results.tsv.orig create mode 100755 rt/share/html/Ticket/Create.html.orig create mode 100644 rt/share/html/Ticket/Elements/EditTransactionCustomFields.orig create mode 100755 rt/share/html/Ticket/Update.html.orig (limited to 'rt/share/html') diff --git a/rt/share/html/Admin/Users/Modify.html b/rt/share/html/Admin/Users/Modify.html index 814e7f996..2483e5b7f 100755 --- a/rt/share/html/Admin/Users/Modify.html +++ b/rt/share/html/Admin/Users/Modify.html @@ -109,7 +109,7 @@ <&| /Widgets/TitleBox, title => loc('Access control') &> - /> + /> <&|/l&>Let this user access RT
diff --git a/rt/share/html/Admin/Users/Modify.html.orig b/rt/share/html/Admin/Users/Modify.html.orig new file mode 100755 index 000000000..814e7f996 --- /dev/null +++ b/rt/share/html/Admin/Users/Modify.html.orig @@ -0,0 +1,421 @@ +%# BEGIN BPS TAGGED BLOCK {{{ +%# +%# COPYRIGHT: +%# +%# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC +%# +%# +%# (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 }}} +<& /Admin/Elements/Header, Title => $title &> +<& /Elements/Tabs &> + +<& /Elements/ListActions, actions => \@results &> + +
+%if ($Create) { + +% } else { + +% } + + + + + + + + + +
+<&| /Widgets/TitleBox, title => loc('Identity') &> + + + + + + + + + +
+<&|/l&>Username: + + <&|/l&>(required) +
+<&|/l&>Email: + + +
+<&|/l&>Real Name: + + +
+<&|/l&>Nickname: + + +
+<&|/l&>Unix login: + + +
+<&|/l&>Language: + +<& /Elements/SelectLang, Name => 'Lang', Default => $UserObj->Lang||$Lang &> +
+<&|/l&>Extra info: + + +
+ +
+ +<&| /Widgets/TitleBox, title => loc('Customers') &> +<& /Elements/EditCustomers, Object => $UserObj, CustomerString=> $CustomerString, ServiceString => $ServiceString &> + +
+ +<&| /Widgets/TitleBox, title => loc('Access control') &> + + /> +<&|/l&>Let this user access RT
+ + + + /> <&|/l&>Let this user be granted rights (<&|/l&>Privileged)
+ +<& /Elements/EditPassword, + User => $UserObj, + Name => [qw(CurrentPass Pass1 Pass2)], +&> + +% $m->callback( %ARGS, CallbackName => 'LeftColumnBottom', UserObj => $UserObj ); +
+<&| /Widgets/TitleBox, title => loc('Location') &> + + + + + + + + +
+<&|/l&>Organization: + + +
+<&|/l&>Address1: + + +
+<&|/l&>Address2: + + +
+<&|/l&>City: + + + +
+<&|/l&>State: + + + +
+<&|/l&>Zip: + + +
+<&|/l&>Country: + + +
+ +
+<&| /Widgets/TitleBox, title => loc('Phone numbers') &> + + + + + + +
+<&|/l&>Residence: + +
+
+<&|/l&>Work: + +
+
+<&|/l&>Mobile: + +
+
+<&|/l&>Pager: + +
+
+ +
+<&| /Widgets/TitleBox, title => loc('Custom Fields') &> + +% my $CFs = $UserObj->CustomFields; +% while (my $CF = $CFs->Next) { + +% } +
+<% loc($CF->Name) %>: + +% if ($UserObj->id) { +<& /Elements/EditCustomField, %ARGS, Object => $UserObj, CustomField => $CF &> +% } else { +<& /Elements/EditCustomField, %ARGS, NamePrefix => 'Object-RT::User--CustomField-', CustomField => $CF &> +% } +
+ +% $m->callback( %ARGS, CallbackName => 'RightColumnBottom', UserObj => $UserObj ); +
+<&| /Widgets/TitleBox, title => loc('Comments about this user') &> + + +%if (!$Create && $UserObj->Privileged) { +
+<&| /Widgets/TitleBox, title => loc('Signature') &> + + +% } + +
+ +% if ( $Create ) { +<& /Elements/Submit, Label => loc('Create') &> +% } else { +<& /Elements/Submit, Label => loc('Save Changes') &> +% } +
+ +<%INIT> + +my $UserObj = RT::User->new($session{'CurrentUser'}); +my ($title, $PrivilegedChecked, $EnabledChecked, $Disabled, $result, @results); + +my ($val, $msg); + +if ($Create) { + $title = loc("Create a new user"); +} +else { + + if ( defined $id && $id eq 'new') { + ( $val, $msg ) = $UserObj->Create( + Name => $Name, + EmailAddress => $ARGS{'EmailAddress'}, + Name => $ARGS{'Name'}, + Comments => $ARGS{'Comments'}, + Signature => $ARGS{'Signature'}, + EmailAddress => $ARGS{'EmailAddress'}, + FreeformContactInfo => $ARGS{'FreeformContactInfo'}, + Organization => $ARGS{'Organization'}, + RealName => $ARGS{'RealName'}, + NickName => $ARGS{'NickName'}, + Lang => $ARGS{'Lang'}, + EmailEncoding => $ARGS{'EmailEncoding'}, + WebEncoding => $ARGS{'WebEncoding'}, + ExternalContactInfoId => $ARGS{'ExternalContactInfoId'}, + ContactInfoSystem => $ARGS{'ContactInfoSystem'}, + Gecos => $ARGS{'Gecos'}, + ExternalAuthId => $ARGS{'ExternalAuthId'}, + AuthSystem => $ARGS{'AuthSystem'}, + HomePhone => $ARGS{'HomePhone'}, + WorkPhone => $ARGS{'WorkPhone'}, + MobilePhone => $ARGS{'MobilePhone'}, + PagerPhone => $ARGS{'PagerPhone'}, + Address1 => $ARGS{'Address1'}, + Address2 => $ARGS{'Address2'}, + City => $ARGS{'City'}, + State => $ARGS{'State'}, + Zip => $ARGS{'Zip'}, + Country => $ARGS{'Country'}, + Privileged => $ARGS{'Privileged'}, + Disabled => ($ARGS{'Enabled'} ? 0 : 1) + ); + + if ($val) { + push @results, $msg; + push @results, ProcessObjectCustomFieldUpdates( ARGSRef => \%ARGS, Object => $UserObj ); + } else { + push @results, loc('User could not be created: [_1]', $msg); + } + } else { + $UserObj->Load($id) || $UserObj->Load($Name) + || Abort("Couldn't load user '" . ( $Name || '') . "'"); + $val = $UserObj->Id(); + } + + if ($val) { + $title = loc("Modify the user [_1]", $UserObj->Name); + } + + # If the create failed + else { + $title = loc("Create a new user"); + $Create = 1; + } +} + + +$m->callback( %ARGS, CallbackName => 'BeforeUpdate', User => $UserObj, ARGSRef => \%ARGS, Results => \@results ); + + +# If we have a user to modify, lets try. +if ($UserObj->Id && $id ne 'new') { + + my @fields = qw(Name Comments Signature EmailAddress FreeformContactInfo + Organization RealName NickName Lang EmailEncoding WebEncoding + ExternalContactInfoId ContactInfoSystem Gecos ExternalAuthId + AuthSystem HomePhone WorkPhone MobilePhone PagerPhone Address1 + Address2 City State Zip Country + ); + + my @fieldresults = UpdateRecordObject ( AttributesRef => \@fields, + Object => $UserObj, + ARGSRef => \%ARGS ); + push (@results,@fieldresults); + push @results, ProcessObjectCustomFieldUpdates( ARGSRef => \%ARGS, Object => $UserObj ); + + #deal with freeside customer links + push @results, ProcessObjectCustomers( ARGSRef => \%ARGS, Object => $UserObj ); + + # {{{ Deal with special fields: Privileged, Enabled + if ( $SetPrivileged and $Privileged != $UserObj->Privileged ) { + my ($code, $msg) = $UserObj->SetPrivileged($Privileged); + push @results, loc('Privileged status: [_1]', loc_fuzzy($msg)); + } + + #we're asking about enabled on the web page but really care about disabled. + $Disabled = $Enabled ? 0 : 1; + + if ( ($SetEnabled) and ( $Disabled != $UserObj->Disabled) ) { + my ($code, $msg) = $UserObj->SetDisabled($Disabled); + push @results, $msg; + } + + +} + + +my %password_cond = $UserObj->CurrentUserRequireToSetPassword; +if ( $UserObj->Id ) { + # Deal with Password field + 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."); + } +} + + +# Do some setup for the ui +unless ( $UserObj->id && $UserObj->Disabled ) { + $EnabledChecked = 'checked="checked"'; +} + +if ((!$Create && $UserObj->Privileged()) or (!$UserObj->Id and $Privileged)) { + $PrivilegedChecked = 'checked="checked"'; +} + +# This code does automatic redirection if any updates happen. +MaybeRedirectForResults( + Actions => \@results, + Arguments => { id => $UserObj->Id }, +) if $UserObj->Id; + + + + +<%ARGS> +$id => undef +$Name => undef +$Comments => undef +$Signature => undef +$EmailAddress => undef +$FreeformContactInfo => undef +$Organization => undef +$RealName => undef +$NickName => undef +$Privileged => undef +$SetPrivileged => undef +$Enabled => undef +$SetEnabled => undef +$Lang => undef +$EmailEncoding => undef +$WebEncoding => undef +$ExternalContactInfoId => undef +$ContactInfoSystem => undef +$Gecos => undef +$ExternalAuthId => undef +$AuthSystem => undef +$HomePhone => undef +$WorkPhone => undef +$MobilePhone => undef +$PagerPhone => undef +$Address1 => undef +$Address2 => undef +$City => undef +$State => undef +$Zip => undef +$Country => undef +$CurrentPass => undef +$Pass1 => undef +$Pass2 => undef +$Create=> undef +$OnlySearchForCustomers => undef +$OnlySearchForServices => undef +$CustomerString => undef +$ServiceString => undef + diff --git a/rt/share/html/Approvals/index.html b/rt/share/html/Approvals/index.html index 97f360ac0..dbdc11ec5 100755 --- a/rt/share/html/Approvals/index.html +++ b/rt/share/html/Approvals/index.html @@ -72,12 +72,9 @@ foreach my $arg ( keys %ARGS ) { next if $skip_update; if ( $ARGS{ "Approval-" . $ticket->Id . "-Notes" } ) { - my $notes = MIME::Entity->build( - Data => [ $ARGS{ "Approval-" . $ticket->Id . "-Notes" } ] - ); - RT::I18N::SetMIMEEntityToUTF8($notes); # convert text parts into utf-8 - - my ( $notesval, $notesmsg ) = $ticket->Correspond( MIMEObj => $notes ); + my ( $notesval, $notesmsg ) = $ticket->Correspond( + Content => $ARGS{ "Approval-" . $ticket->Id . "-Notes" } + ); if ($notesval) { push ( @actions, loc("Approval #[_1]: Notes recorded",$ticket->Id )); } else { diff --git a/rt/share/html/Elements/.CalendarDaySchedule.swp b/rt/share/html/Elements/.CalendarDaySchedule.swp new file mode 100644 index 000000000..f79cd0938 Binary files /dev/null and b/rt/share/html/Elements/.CalendarDaySchedule.swp differ diff --git a/rt/share/html/Elements/.CalendarEventWeekly.swp b/rt/share/html/Elements/.CalendarEventWeekly.swp new file mode 100644 index 000000000..af6c22220 Binary files /dev/null and b/rt/share/html/Elements/.CalendarEventWeekly.swp differ diff --git a/rt/share/html/Elements/.CalendarSlotSchedule.swp b/rt/share/html/Elements/.CalendarSlotSchedule.swp new file mode 100644 index 000000000..6b8a8f9c2 Binary files /dev/null and b/rt/share/html/Elements/.CalendarSlotSchedule.swp differ diff --git a/rt/share/html/Elements/CalendarSlotSchedule.dynamic b/rt/share/html/Elements/CalendarSlotSchedule.dynamic new file mode 100644 index 000000000..88202d417 --- /dev/null +++ b/rt/share/html/Elements/CalendarSlotSchedule.dynamic @@ -0,0 +1,93 @@ +<%ARGS> + $Date => undef, + @Tickets => () + $slots => $default_slots, + $sday => undef, + $tod_row => undef, + $timestep => $default_timestep, + @username => () + +<%SHARED> +my @slots = ( [], [], [], [], [], [], [] ); + +% #for my $t ( @{ $Tickets{$date->strftime("%F")} } ) { +% for my $t (@Tickets) { +% +% my($sm, $sh) = ($t->StartsObj->Localtime('user'))[1,2]; +% my $starts = $sh*60 + $sm; +% +% if ( RTx::Calendar::LocalDate($t->StartsObj->Unix) eq $Date->strftime('%F') #today +% && $starts >= $tod_row && $starts < ($tod_row + $timestep) ) { +% #then we're a new entry, find a slot for us +% my $s = 0; +% while ( ref($slots[$sday]->[$s]) ) { $s++ } +% $slots[$sday]->[$s] = [ $t->Id, $t ]; +% } +% +% my($dm, $dh) = ($t->DueObj->Localtime('user'))[1,2]; +% my $due = $dh*60 + $dm; +% +% if ( RTx::Calendar::LocalDate($t->DueObj->Unix) eq $Date->strftime('%F') #today +% && $due <= $tod_row && $due > ($tod_row + $timestep ) ) { +% #then find our slot and remove us +% @{ $slots[$sday] } = +% map { (!ref($_) || $_->[0] != $t->Id) ? $_ : '' } +% @{ $slots[$sday] }; +% } +% +% } +% +% pop @{ $slots[$sday] } while @{ $slots[$sday] } && !ref($slots[$sday]->[-1]); +% +% #now display: +% +% if ( scalar(@{$slots[$sday]}) > $slots ) { +% #overflow situation, eek... could be handled better, how? + + + class="weekly +%# <% $is_today ? 'today' +%# : $is_yesterday ? 'yesterday' +%# : $is_aweekago ? 'aweekago' +%# : '' +%# %> + " + >MULTIPLE + + +% } else { +% +% foreach my $slot ( @{ $slots[$sday] } ) { +% my( $id, $ticket ) = @$slot; + + <% $id %> + + +% } +% +% if ( scalar(@{$slots[$sday]}) < $slots ) { + + + class="weekly +%# <% $is_today ? 'today' +%# : $is_yesterday ? 'yesterday' +%# : $is_aweekago ? 'aweekago' +%# : '' +%# %> + " + > + +% } +% +% } +<%ONCE> +my $default_slots = RT->Config->Get('CalendarWeeklySlots') || 5; +my $default_timestep = RT->Config->Get('CalendarWeeklySizeMin') || 30; #1/2h + diff --git a/rt/share/html/Elements/EditCustomFieldDate b/rt/share/html/Elements/EditCustomFieldDate index f62f04704..c430b0b33 100644 --- a/rt/share/html/Elements/EditCustomFieldDate +++ b/rt/share/html/Elements/EditCustomFieldDate @@ -46,7 +46,7 @@ %# %# END BPS TAGGED BLOCK }}} % my $name = $NamePrefix.$CustomField->Id.'-Values'; -<& /Elements/SelectDate, Name => "$name", current => 0, ShowTime => 0 &> (<%$DateObj->AsString(Time => 0, Timezone => 'utc')%>) +<& /Elements/SelectDate, Name => "$name", current => 0, ShowTime => 0, $KeepValue && $Default ? (Default => $Default) : () &> (<%$DateObj->AsString(Time => 0, Timezone => 'utc')%>) <%INIT> my $DateObj = RT::Date->new ( $session{'CurrentUser'} ); @@ -59,4 +59,5 @@ $NamePrefix => undef $Default => undef $Values => undef $MaxValues => 1 +$KeepValue => undef diff --git a/rt/share/html/Elements/EditCustomFieldDateTime b/rt/share/html/Elements/EditCustomFieldDateTime index edf125e80..b50ea431a 100644 --- a/rt/share/html/Elements/EditCustomFieldDateTime +++ b/rt/share/html/Elements/EditCustomFieldDateTime @@ -46,7 +46,7 @@ %# %# END BPS TAGGED BLOCK }}} % my $name = $NamePrefix.$CustomField->Id.'-Values'; -<& /Elements/SelectDate, Name => "$name", current => 0 &> (<%$DateObj->AsString%>) +<& /Elements/SelectDate, Name => "$name", current => 0, $KeepValue && $Default ? (Default => $Default) : () &> (<%$DateObj->AsString($KeepValue ? ( Timezone => 'utc' ) : () )%>) <%INIT> my $DateObj = RT::Date->new ( $session{'CurrentUser'} ); @@ -60,4 +60,5 @@ $Default => undef $Values => undef $MaxValues => 1 $Format => 'ISO' +$KeepValue => undef diff --git a/rt/share/html/Elements/Error b/rt/share/html/Elements/Error index b2042610e..d747c4e5b 100755 --- a/rt/share/html/Elements/Error +++ b/rt/share/html/Elements/Error @@ -78,11 +78,7 @@ $SuppressHeader => 0, my $error = "WebRT: $Why"; $error .= " ($Details)" if defined $Details && length $Details; -# TODO: Log::Dispatch isn't UTF-8 safe. Autrijus needs to talk to dave rolsky about getting this fixed -use Encode (); -Encode::_utf8_off($error); - -$RT::Logger->error($error); +$RT::Logger->error( $error ); if ( $session{'REST'} ) { $r->content_type('text/plain'); diff --git a/rt/share/html/NoAuth/css/.calendar.css.swp b/rt/share/html/NoAuth/css/.calendar.css.swp new file mode 100644 index 000000000..cbc46cd5e Binary files /dev/null and b/rt/share/html/NoAuth/css/.calendar.css.swp differ diff --git a/rt/share/html/NoAuth/css/aileron/ticket.css b/rt/share/html/NoAuth/css/aileron/ticket.css index 0d60f6ada..bc6315001 100644 --- a/rt/share/html/NoAuth/css/aileron/ticket.css +++ b/rt/share/html/NoAuth/css/aileron/ticket.css @@ -223,22 +223,6 @@ div#ticket-history .messagebody .messagebody{ .ticket-summary .titlebox-title .left a, .ticket-summary .titlebox-title .left a:visited { color: #fff;} -.unread-messages .titlebox , .unread-messages .titlebox-title .left { - border: 1px solid #99a; - border-right: 2px solid #aab; - border-bottom: 2px solid #aab; - -} - - -.unread-messages .titlebox { - background-color: #dde; -} - -.unread-messages .titlebox-title .left { - background-color: #cce; -} - .ticket-inactive { text-decoration: line-through; color: #666 diff --git a/rt/share/html/NoAuth/css/base/ticket.css b/rt/share/html/NoAuth/css/base/ticket.css index 6a43a1db1..d30b04645 100644 --- a/rt/share/html/NoAuth/css/base/ticket.css +++ b/rt/share/html/NoAuth/css/base/ticket.css @@ -143,4 +143,7 @@ display: none; } +.unread-messages .titlebox-content :link { + text-decoration: underline; +} diff --git a/rt/share/html/NoAuth/iCal/dhandler b/rt/share/html/NoAuth/iCal/dhandler index 35da94080..46c272921 100644 --- a/rt/share/html/NoAuth/iCal/dhandler +++ b/rt/share/html/NoAuth/iCal/dhandler @@ -48,7 +48,6 @@ <%init> use Data::ICal; use Data::ICal::Entry::Event; -use Encode (); my $path = $m->dhandler_arg; @@ -62,8 +61,8 @@ $notfound->() unless $path =~ m!^([^/]+)/([^/]+)/(.*)(\.(ical|ics))?!; my ($name, $auth, $search) = ($1, $2, $3); # Unescape parts $_ =~ s/\%([0-9a-z]{2})/chr(hex($1))/gei for $name, $search; -# convert to perl strings -$_ = Encode::decode_utf8( $_ ) for $name, $search; +# Decode from bytes to characters +$_ = Encode::decode( "UTF-8", $_ ) for $name, $search; my $user = RT::User->new( RT->SystemUser ); $user->Load( $name ); diff --git a/rt/share/html/NoAuth/images/week-collapse.xcf b/rt/share/html/NoAuth/images/week-collapse.xcf new file mode 100644 index 000000000..cbb2b95eb Binary files /dev/null and b/rt/share/html/NoAuth/images/week-collapse.xcf differ diff --git a/rt/share/html/NoAuth/images/week-expand.xcf b/rt/share/html/NoAuth/images/week-expand.xcf new file mode 100644 index 000000000..1ab8e65c8 Binary files /dev/null and b/rt/share/html/NoAuth/images/week-expand.xcf differ diff --git a/rt/share/html/REST/1.0/Forms/ticket/comment b/rt/share/html/REST/1.0/Forms/ticket/comment index 934cbfb68..41320ba4c 100755 --- a/rt/share/html/REST/1.0/Forms/ticket/comment +++ b/rt/share/html/REST/1.0/Forms/ticket/comment @@ -91,8 +91,9 @@ my $ent = MIME::Entity->build( 'X-RT-Interface' => 'REST', ); $ent->attach( - 'Content-Type' => $changes{'Content-Type'} || 'text/plain', - Data => $changes{Text}, + Type => $changes{'Content-Type'} || 'text/plain', + Charset => "UTF-8", + Data => Encode::encode("UTF-8", $changes{Text} ), ) if $changes{Text}; diff --git a/rt/share/html/REST/1.0/Forms/ticket/default b/rt/share/html/REST/1.0/Forms/ticket/default index 2a0c7efa4..33a8935d6 100755 --- a/rt/share/html/REST/1.0/Forms/ticket/default +++ b/rt/share/html/REST/1.0/Forms/ticket/default @@ -191,13 +191,14 @@ else { $v{MIMEObj} = MIME::Entity->build( Type => "multipart/mixed", - From => $session{CurrentUser}->EmailAddress, - Subject => $v{Subject}, + From => Encode::encode( "UTF-8", $session{CurrentUser}->EmailAddress ), + Subject => Encode::encode( "UTF-8", $v{Subject}), 'X-RT-Interface' => 'REST', ); $v{MIMEObj}->attach( - Data => $text, - 'Content-Type' => $v{'Content-Type'} || 'text/plain', + Type => $v{'Content-Type'} || 'text/plain', + Charset => "UTF-8", + Data => Encode::encode( "UTF-8", $text ), ) if $text; my ($status, $msg) = process_attachments($v{'MIMEObj'}, @atts); unless ($status) { diff --git a/rt/share/html/REST/1.0/ticket/comment b/rt/share/html/REST/1.0/ticket/comment index 4c058b6ab..177690d6a 100755 --- a/rt/share/html/REST/1.0/ticket/comment +++ b/rt/share/html/REST/1.0/ticket/comment @@ -108,7 +108,11 @@ my $ent = MIME::Entity->build( Type => "multipart/mixed", 'X-RT-Interface' => 'REST', ); -$ent->attach(Data => $k->{Text}) if $k->{Text}; +$ent->attach( + Type => "text/plain", + Charset => "UTF-8", + Data => Encode::encode( "UTF-8", $k->{Text} ), +) if $k->{Text}; { my ($res, $msg) = process_attachments($ent, @atts); diff --git a/rt/share/html/Schedule/.UserBar.swp b/rt/share/html/Schedule/.UserBar.swp new file mode 100644 index 000000000..0dcd4315e Binary files /dev/null and b/rt/share/html/Schedule/.UserBar.swp differ diff --git a/rt/share/html/Search/.Calendar.html.swp b/rt/share/html/Search/.Calendar.html.swp new file mode 100644 index 000000000..3e3788220 Binary files /dev/null and b/rt/share/html/Search/.Calendar.html.swp differ diff --git a/rt/share/html/Search/.Schedule.html.swp b/rt/share/html/Search/.Schedule.html.swp new file mode 100644 index 000000000..e88b29135 Binary files /dev/null and b/rt/share/html/Search/.Schedule.html.swp differ diff --git a/rt/share/html/Search/Bulk.html.orig b/rt/share/html/Search/Bulk.html.orig new file mode 100755 index 000000000..38ca64248 --- /dev/null +++ b/rt/share/html/Search/Bulk.html.orig @@ -0,0 +1,460 @@ +%# BEGIN BPS TAGGED BLOCK {{{ +%# +%# COPYRIGHT: +%# +%# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC +%# +%# +%# (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 }}} +<& /Elements/Header, Title => $title &> +<& /Elements/Tabs &> + +<& /Elements/ListActions, actions => \@results &> +
+% foreach my $var (qw(Query Format OrderBy Order Rows Page SavedChartSearchId)) { + +%} +<& /Elements/CollectionList, + Query => $Query, + DisplayFormat => $Format, + Format => $ARGS{'Format'}, + Verbatim => 1, + AllowSorting => 1, + OrderBy => $OrderBy, + Order => $Order, + Rows => $Rows, + Page => $Page, + BaseURL => RT->Config->Get('WebPath')."/Search/Bulk.html?", + Class => 'RT::Tickets' + &> + +% $m->callback(CallbackName => 'AfterTicketList', ARGSRef => \%ARGS); + +
+ +<& /Elements/Submit, Label => loc('Update'), CheckboxNameRegex => '/^UpdateTicket\d+$/', CheckAll => 1, ClearAll => 1 &> +
+<&|/Widgets/TitleBox, title => $title &> + + + + + +
+ + + + + + + + + + + + + + + +
<&|/l&>Make Owner: <& /Elements/SelectOwner, Name => "Owner", Default => $ARGS{Owner} || '' &> +( /> <&|/l&>Force change)
<&|/l&>Add Requestor:
<&|/l&>Remove Requestor:
<&|/l&>Add Cc:
<&|/l&>Remove Cc:
<&|/l&>Add AdminCc:
<&|/l&>Remove AdminCc:
+
+ + + + +% my $rel = ($ARGS{Priority} =~ s/^R//); + + + + + + + + + + + + + + + +
<&|/l&>Make subject:
<&|/l&>Make priority: <& /Elements/SelectPriority, Name => "Priority", Default => $ARGS{Priority} &> + +
<&|/l&>Make queue: <& /Elements/SelectQueue, Name => "Queue", Default => $ARGS{Queue} &>
<&|/l&>Make Status: <& /Elements/SelectStatus, Name => "Status", Default => $ARGS{Status}, Queues => $seen_queues &>
<&|/l&>Make date Starts: <& /Elements/SelectDate, Name => "Starts_Date", Default => $ARGS{Starts_Date} || '' &>
<&|/l&>Make date Started: <& /Elements/SelectDate, Name => "Started_Date", Default => $ARGS{Started_Date} || '' &>
<&|/l&>Make date Told: <& /Elements/SelectDate, Name => "Told_Date", Default => $ARGS{Told_Date} || '' &>
<&|/l&>Make date Due: <& /Elements/SelectDate, Name => "Due_Date", Default => $ARGS{Due_Date} || '' &>
<&|/l&>Make date Resolved: <& /Elements/SelectDate, Name => "Resolved_Date", Default => $ARGS{Resolved_Date} || '' &>
+ +
+ +<&| /Widgets/TitleBox, title => loc('Add comments or replies to selected tickets') &> + + + + +% while (my $CF = $TxnCFs->Next()) { + + + + +% } # end if while + +<& /Ticket/Elements/AddAttachments, %ARGS &> + + +
<&|/l&>Update Type: +
<&|/l&>Subject: " />
<% $CF->Name %>:<& /Elements/EditCustomField, + CustomField => $CF, + NamePrefix => "Object-RT::Transaction--CustomField-", + Default => $ARGS{"Object-RT::Transaction--CustomField-" . $CF->id . '-Values'} || + $ARGS{"Object-RT::Transaction--CustomField-" . $CF->id . '-Value'}, + &><% $CF->FriendlyType %>
<&|/l&>Message: +%# 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", + $ARGS{UpdateContent} ? ( Default => $ARGS{UpdateContent}, IncludeSignature => 0 ) : + ( IncludeSignature => $IncludeSignature ), + &> +
+ + + +<%perl> +my $cfs = RT::CustomFields->new($session{'CurrentUser'}); +$cfs->LimitToGlobal(); +$cfs->LimitToQueue($_) for keys %$seen_queues; + + +% if ($cfs->Count) { +<&|/Widgets/TitleBox, title => loc('Edit Custom Fields'), color => "#336633"&> + + + + + + +% while (my $cf = $cfs->Next()) { + + +% my $rows = 5; +% my $cf_id = $cf->id; +% my @add = (NamePrefix => 'Bulk-Add-CustomField-', CustomField => $cf, Rows => $rows, +% Multiple => ($cf->MaxValues ==1 ? 0 : 1) , Cols => 25, +% Default => $ARGS{"Bulk-Add-CustomField-$cf_id-Values"} || $ARGS{"Bulk-Add-CustomField-$cf_id-Value"}, ); +% my @del = (NamePrefix => 'Bulk-Delete-CustomField-', CustomField => $cf, +% Rows => $rows, Multiple => 1, Cols => 25, +% Default => $ARGS{"Bulk-Delete-CustomField-$cf_id-Values"} || $ARGS{"Bulk-Delete-CustomField-$cf_id-Value"}, ); +% if ($cf->Type eq 'Select') { + + +% } elsif ($cf->Type eq 'Combobox') { + + +% } elsif ($cf->Type eq 'Freeform') { + + +% } elsif ($cf->Type eq 'Text') { + + +% } elsif ($cf->Type eq 'Date') { + + +% } elsif ($cf->Type eq 'DateTime') { +% # Pass datemanip format to prevent another tz date conversion + + +% } else { +% $RT::Logger->crit("Unknown CustomField type: " . $cf->Type); +% } + +% } +
<&|/l&>Name<&|/l&>Add values<&|/l&>Delete values
<% loc($cf->Name) %>
+(<%$cf->FriendlyType%>)
<& /Elements/EditCustomFieldSelect, @add &><& /Elements/EditCustomFieldSelect, @del &><& /Elements/EditCustomFieldCombobox, @add &><& /Elements/EditCustomFieldCombobox, @del &><& /Elements/EditCustomFieldFreeform, @add &><& /Elements/EditCustomFieldFreeform, @del &><& /Elements/EditCustomFieldText, @add &> <& /Elements/EditCustomFieldDate, @add, Default => undef &><& /Elements/EditCustomFieldDate, @del, Default => undef &><& /Elements/EditCustomFieldDateTime, @add, Default => undef, Format => 'datemanip' &><& /Elements/EditCustomFieldDateTime, @del, Default => undef, Format => 'datemanip' &>
+ +% } + +<&|/Widgets/TitleBox, title => loc('Edit Links'), color => "#336633"&> +<&|/l&>Enter tickets or URIs to link tickets to. Separate multiple entries with spaces.
+<& /Ticket/Elements/BulkLinks, Tickets => $Tickets, $ARGS{'AddMoreAttach'} ? %ARGS : () &> + + +<& /Elements/Submit, Label => loc('Update') &> + + +
+ + +<%INIT> +unless ( defined $Rows ) { + $Rows = $RowsPerPage; + $ARGS{Rows} = $RowsPerPage; +} +my $title = loc("Update multiple tickets"); + +# Iterate through the ARGS hash and remove anything with a null value. +map ( $ARGS{$_} =~ /^$/ && ( delete $ARGS{$_} ), keys %ARGS ); + +my (@results); + +ProcessAttachments(ARGSRef => \%ARGS); + +$Page ||= 1; + +$Format ||= RT->Config->Get('DefaultSearchResultFormat'); + +# inject _CHECKBOX to the first field. +$Format =~ s/'?([^']+)'?,/'___CHECKBOX__$1',/; #' + +my $Tickets = RT::Tickets->new( $session{'CurrentUser'} ); +$Tickets->FromSQL($Query); +if ( $OrderBy =~ /\|/ ) { + + # Multiple Sorts + my @OrderBy = split /\|/, $OrderBy; + my @Order = split /\|/, $Order; + $Tickets->OrderByCols( + map { { FIELD => $OrderBy[$_], ORDER => $Order[$_] } } + ( 0 .. $#OrderBy ) ); +} +else { + $Tickets->OrderBy( FIELD => $OrderBy, ORDER => $Order ); +} + +$Tickets->RowsPerPage($Rows) if ($Rows); +$Tickets->GotoPage( $Page - 1 ); # SB uses page 0 as the first page + +Abort( loc("No search to operate on.") ) unless ($Tickets); + +# build up a list of all custom fields for tickets that we're displaying, so +# we can display sane edit widgets. + +my $fields = {}; +my $seen_queues = {}; +while ( my $ticket = $Tickets->Next ) { + next if $seen_queues->{ $ticket->Queue }++; + + my $custom_fields = $ticket->CustomFields; + while ( my $field = $custom_fields->Next ) { + $fields->{ $field->id } = $field; + } +} + +#Iterate through each ticket we've been handed +my @linkresults; + +$Tickets->RedoSearch(); + +# pull out the labels for any custom fields we want to update + +my $cf_del_keys; +@$cf_del_keys = grep { /^Bulk-Delete-CustomField/ } keys %ARGS; +my $cf_add_keys; +@$cf_add_keys = grep { /^Bulk-Add-CustomField/ } keys %ARGS; + +if ( defined($ARGS{'Priority'}) + and ($ARGS{'Priority-Mode'} || '') eq 'relative' ) { + # magic in Ticket::SetPriority + $ARGS{'Priority'} = 'R'.$ARGS{'Priority'}; +} +delete $ARGS{'Priority-Mode'}; + +unless ( $ARGS{'AddMoreAttach'} ) { + # Add session attachments if any to be processed by ProcessUpdateMessage + $ARGS{'UpdateAttachments'} = $session{'Attachments'} if ( $session{'Attachments'} ); + + while ( my $Ticket = $Tickets->Next ) { + next unless ( $ARGS{ "UpdateTicket" . $Ticket->Id } ); + + #Update the links + $ARGS{'id'} = $Ticket->id; + + my @updateresults = ProcessUpdateMessage( + TicketObj => $Ticket, + ARGSRef => \%ARGS, + ); + + #Update the basics. + my @basicresults = + ProcessTicketBasics( TicketObj => $Ticket, ARGSRef => \%ARGS ); + my @dateresults = + ProcessTicketDates( TicketObj => $Ticket, ARGSRef => \%ARGS ); + + #Update the watchers + my @watchresults = + ProcessTicketWatchers( TicketObj => $Ticket, ARGSRef => \%ARGS ); + + foreach my $type (qw(MergeInto DependsOn MemberOf RefersTo)) { + $ARGS{ $Ticket->id . "-" . $type } = $ARGS{"Ticket-$type"}; + $ARGS{ $type . "-" . $Ticket->id } = $ARGS{"$type-Ticket"}; + } + @linkresults = + ProcessTicketLinks( TicketObj => $Ticket, ARGSRef => \%ARGS ); + foreach my $type (qw(MergeInto DependsOn MemberOf RefersTo)) { + delete $ARGS{ $type . "-" . $Ticket->id }; + delete $ARGS{ $Ticket->id . "-" . $type }; + } + + my @cfresults; + + foreach my $list ( $cf_add_keys, $cf_del_keys ) { + next unless $list->[0]; + + + my $op; + if ( $list->[0] =~ /Add/ ) { + $op = 'add'; + + } + elsif ( $list->[0] =~ /Del/ ) { + $op = 'del'; + } + else { + $RT::Logger->crit( + "Got an op that was neither add nor delete. can never happen" + . $list->[0] ); + last; + } + + foreach my $key (@$list) { + my ( $cfid, $cf ); + next if $key =~ /CustomField-(\d+)-Category$/; + if ( $key =~ /CustomField-(\d+)-/ ) { + $cfid = $1; + $cf = RT::CustomField->new( $session{'CurrentUser'} ); + $cf->Load($cfid); + } + else {next} + my @values = + ref( $ARGS{$key} ) eq 'ARRAY' + ? @{ $ARGS{$key} } + : ( $ARGS{$key} ); + map { s/(\r\n|\r)/\n/g; } @values; # fix the newlines + # now break the multiline values into multivalues + @values = map { split( /\n/, $_ ) } @values + unless ( $cf->SingleValue ); + + my $current_values = $Ticket->CustomFieldValues($cfid); + + if ( $cf->Type eq 'DateTime' || $cf->Type eq 'Date' ){ + # Clear out empty string submissions to avoid + # Not set changed to Not set + @values = grep length, @values; + } + + foreach my $value (@values) { + + # Convert for timezone. Without converstion, + # HasEntry and DeleteCustomFieldValue fail because + # the value in the DB is converted. + if ( $op eq 'del' + && ($cf->Type eq 'DateTime' || $cf->Type eq 'Date') ){ + my $DateObj = RT::Date->new( $session{'CurrentUser'} ); + $DateObj->Set( Format => 'unknown', + Value => $value ); + $value = $cf->Type eq 'DateTime' ? $DateObj->ISO + : $DateObj->ISO(Time => 0, Seconds => 0); + } + + if ( $op eq 'del' && $current_values->HasEntry($value) ) { + my ( $id, $msg ) = $Ticket->DeleteCustomFieldValue( + Field => $cfid, + Value => $value + ); + push @cfresults, $msg; + } + + elsif ( $op eq 'add' && !$current_values->HasEntry($value) ) { + my ( $id, $msg ) = $Ticket->AddCustomFieldValue( + Field => $cfid, + Value => $value + ); + push @cfresults, $msg; + } + } + } + } + my @statusresults = + ProcessTicketStatus( TicketObj => $Ticket, ARGSRef => \%ARGS ); + + my @tempresults = ( + @watchresults, @basicresults, @dateresults, + @updateresults, @linkresults, @cfresults, + @statusresults + ); + + @tempresults = + map { + $_ =~ /^Ticket \d+:/ ? $_ : + loc( "Ticket [_1]: [_2]", $Ticket->Id, $_ ) + } @tempresults; + + @results = ( @results, @tempresults ); + } + + # Cleanup WebUI + delete $session{'Attachments'}; + + $Tickets->RedoSearch(); +} + +my $TxnCFs = RT::CustomFields->new( $session{CurrentUser} ); +$TxnCFs->LimitToLookupType( RT::Transaction->CustomFieldLookupType ); +$TxnCFs->LimitToGlobalOrObjectId( keys %$seen_queues ); + + +<%args> +$Format => undef +$Page => 1 +$Rows => undef +$RowsPerPage => undef +$Order => 'ASC' +$OrderBy => 'id' +$Query => undef +$SavedSearchId => undef +$SavedChartSearchId => undef + diff --git a/rt/share/html/Search/Elements/ResultsRSSView b/rt/share/html/Search/Elements/ResultsRSSView index d08771124..a453a8603 100644 --- a/rt/share/html/Search/Elements/ResultsRSSView +++ b/rt/share/html/Search/Elements/ResultsRSSView @@ -46,8 +46,6 @@ %# %# END BPS TAGGED BLOCK }}} <%INIT> -use Encode (); - my $old_current_user; if ( $m->request_comp->path =~ RT->Config->Get('WebNoAuthRegex') ) { @@ -67,8 +65,8 @@ if ( $m->request_comp->path =~ RT->Config->Get('WebNoAuthRegex') ) { # Unescape parts $name =~ s/\%([0-9a-z]{2})/chr(hex($1))/gei; - # convert to perl strings - $name = Encode::decode_utf8($name); + # Decode from bytes to characters + $name = Encode::decode( "UTF-8", $name ); my $user = RT::User->new(RT->SystemUser); $user->Load($name); diff --git a/rt/share/html/Search/Results.tsv b/rt/share/html/Search/Results.tsv index 6d8253e78..376db0ed4 100644 --- a/rt/share/html/Search/Results.tsv +++ b/rt/share/html/Search/Results.tsv @@ -71,7 +71,7 @@ my $col_entry = sub { delete $col->{title} if $col->{title} and $col->{title} =~ /^\s*#\s*$/; return { - header => Encode::encode_utf8(loc($col->{title} || $col->{attribute})), + header => loc($col->{title} || $col->{attribute}), map => $m->comp( "/Elements/ColumnMap", Name => $col->{attribute}, @@ -128,7 +128,7 @@ while (my $row = $Tickets->Next) { # remove tabs from all field values, they screw up the tsv $val = '' unless defined $val; $val =~ s/(?:\n|\r)//g; $val =~ s{\t}{ }g; - Encode::encode_utf8($val); + $val; } @$col)."\n"); } } diff --git a/rt/share/html/Search/Results.tsv.orig b/rt/share/html/Search/Results.tsv.orig new file mode 100644 index 000000000..6d8253e78 --- /dev/null +++ b/rt/share/html/Search/Results.tsv.orig @@ -0,0 +1,137 @@ +%# BEGIN BPS TAGGED BLOCK {{{ +%# +%# COPYRIGHT: +%# +%# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC +%# +%# +%# (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> +$Format => undef +$Query => '' +$OrderBy => 'id' +$Order => 'ASC' +$PreserveNewLines => 0 + +<%INIT> + +$r->content_type('text/tab-separated-values'); +$r->header_out('Content-Disposition' => 'attachment;filename="Results.tsv"'); + +my $DisplayFormat = $m->comp('/Elements/ScrubHTML', Content => $Format); + +my @Format = $m->comp('/Elements/CollectionAsTable/ParseFormat', Format => $DisplayFormat); + +my @columns; + +my $should_loc = { map { $_ => 1 } qw(Status) }; + +my $col_entry = sub { + my $col = shift; + # in tsv output, "#" is often a comment character but we use it for "id" + delete $col->{title} + if $col->{title} and $col->{title} =~ /^\s*#\s*$/; + return { + header => Encode::encode_utf8(loc($col->{title} || $col->{attribute})), + map => $m->comp( + "/Elements/ColumnMap", + Name => $col->{attribute}, + Attr => 'value' + ), + should_loc => $should_loc->{$col->{attribute}}, + } +}; + +if ($PreserveNewLines) { + my $col = []; + push @columns, $col; + for (@Format) { + if ($_->{title} eq 'NEWLINE') { + $col = []; + push @columns, $col; + } + else { + push @$col, $col_entry->($_); + } + } +} +else { + push @columns, [map { $_->{attribute} + ? $col_entry->($_) + : () } @Format]; +} + +for (@columns) { + $m->out(join("\t", map { $_->{header} } @$_)."\n"); +} + +my $Tickets = RT::Tickets->new( $session{'CurrentUser'} ); +$Tickets->FromSQL( $Query ); +if ( $OrderBy =~ /\|/ ) { + # Multiple Sorts + my @OrderBy = split /\|/, $OrderBy; + my @Order = split /\|/, $Order; + $Tickets->OrderByCols( + map { { FIELD => $OrderBy[$_], ORDER => $Order[$_] } } + ( 0 .. $#OrderBy ) + ); +} +else { + $Tickets->OrderBy( FIELD => $OrderBy, ORDER => $Order ); +} + +my $ii = 0; +while (my $row = $Tickets->Next) { + for my $col (@columns) { + $m->out(join("\t", map { + my $val = ProcessColumnMapValue($_->{map}, Arguments => [$row, $ii++], Escape => 0); + $val = loc($val) if $_->{should_loc}; + # remove tabs from all field values, they screw up the tsv + $val = '' unless defined $val; + $val =~ s/(?:\n|\r)//g; $val =~ s{\t}{ }g; + Encode::encode_utf8($val); + } @$col)."\n"); + } +} +$m->abort(); + + diff --git a/rt/share/html/Ticket/Create.html b/rt/share/html/Ticket/Create.html index 697db546b..bd60b5c98 100755 --- a/rt/share/html/Ticket/Create.html +++ b/rt/share/html/Ticket/Create.html @@ -105,8 +105,8 @@ % $m->callback( CallbackName => 'AfterOwner', ARGSRef => \%ARGS ); - <& /Ticket/Elements/EditCustomFields, %ARGS, QueueObj => $QueueObj, InTable => 1 &> - <& /Ticket/Elements/EditTransactionCustomFields, %ARGS, QueueObj => $QueueObj, InTable => 1 &> + <& /Ticket/Elements/EditCustomFields, %ARGS, QueueObj => $QueueObj, InTable => 1, KeepValue => 1 &> + <& /Ticket/Elements/EditTransactionCustomFields, %ARGS, QueueObj => $QueueObj, InTable => 1, KeepValue => 1 &> % $m->callback( CallbackName => 'AfterBasics', QueueObj => $QueueObj, ARGSRef => \%ARGS ); diff --git a/rt/share/html/Ticket/Create.html.orig b/rt/share/html/Ticket/Create.html.orig new file mode 100755 index 000000000..697db546b --- /dev/null +++ b/rt/share/html/Ticket/Create.html.orig @@ -0,0 +1,463 @@ +%# BEGIN BPS TAGGED BLOCK {{{ +%# +%# COPYRIGHT: +%# +%# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC +%# +%# +%# (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 }}} +<& /Elements/Header, + Title => $title, + onload => "function () { hide('Ticket-Create-details') }" &> +<& /Elements/Tabs &> + +<& /Elements/ListActions, actions => \@results &> + +
+ + +% $m->callback( CallbackName => 'FormStart', QueueObj => $QueueObj, ARGSRef => \%ARGS ); + +% if ($gnupg_widget) { + <& /Elements/GnuPG/SignEncryptWidget:ShowIssues, self => $gnupg_widget &> +% } + +
+ + +
+ <&| /Widgets/TitleBox, title => loc("Basics"), class=>'ticket-info-basics' &> + + <& /Ticket/Elements/EditBasics, + InTable => 1, + fields => [ + { name => 'Queue', + comp => '/Elements/SelectQueue', + args => { + Name => 'Queue', + Default => $QueueObj->Name, + QueueObj => $QueueObj, + ShowNullOption => 0, + ShowAllQueues => 0, + OnChange => "document.getElementsByName('id')[0].value = 'refresh'; form.submit()", + }, + }, + { name => 'Status', + comp => '/Elements/SelectStatus', + args => { + Name => "Status", + Default => $ARGS{Status} || $QueueObj->Lifecycle->DefaultOnCreate, + DefaultValue => 0, + SkipDeleted => 1, + QueueObj => $QueueObj, + }, + }, + { name => 'Owner', + comp => '/Elements/SelectOwner', + args => { + Name => "Owner", + Default => $ARGS{Owner} || RT->Nobody->Id, + DefaultValue => 0, + QueueObj => $QueueObj, + }, + } + ] + &> + +% $m->callback( CallbackName => 'AfterOwner', ARGSRef => \%ARGS ); + + <& /Ticket/Elements/EditCustomFields, %ARGS, QueueObj => $QueueObj, InTable => 1 &> + <& /Ticket/Elements/EditTransactionCustomFields, %ARGS, QueueObj => $QueueObj, InTable => 1 &> +
+ +% $m->callback( CallbackName => 'AfterBasics', QueueObj => $QueueObj, ARGSRef => \%ARGS ); +
+ +
+ <&| /Widgets/TitleBox, title => $title, class => 'messagedetails' &> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +% if ( $gnupg_widget ) { + +% } + + + + + + <& /Ticket/Elements/AddAttachments, %ARGS, QueueObj => $QueueObj &> +
+<&|/l&>Requestors: + +<& /Elements/EmailInput, Name => 'Requestors', Size => undef, Default => exists($ARGS{Requestors}) ? $ARGS{Requestors} : $session{CurrentUser}->EmailAddress &> +% $m->callback( CallbackName => 'AfterRequestors', QueueObj => $QueueObj, ARGSRef => \%ARGS ); +
+<&|/l&>Cc: +<& /Elements/EmailInput, Name => 'Cc', Size => undef, Default => $ARGS{Cc} &>
  + + <&|/l&>(Sends a carbon-copy of this update to a comma-delimited list of email addresses. These people will receive future updates.) + +
+<&|/l&>Admin Cc: +<& /Elements/EmailInput, Name => 'AdminCc', Size => undef, Default => $ARGS{AdminCc} &>
  + + <&|/l&>(Sends a carbon-copy of this update to a comma-delimited list of administrative email addresses. These people will receive future updates.) + +
+<&|/l&>Subject: + + +% $m->callback( %ARGS, CallbackName => 'AfterSubject' ); +
  +<& /Elements/GnuPG/SignEncryptWidget, self => $gnupg_widget, QueueObj => $QueueObj &> +
+<&|/l&>Describe the issue below:
+% if ( RT->Config->Get('ArticleOnTicketCreate')) { +<& /Articles/Elements/BeforeMessageBox, %ARGS, QueueObj => $QueueObj &> +% } +% $m->callback( %ARGS, QueueObj => $QueueObj, CallbackName => 'BeforeMessageBox' ); +% if (exists $ARGS{Content}) { +<& /Elements/MessageBox, Default => $ARGS{Content}, IncludeSignature => 0 &> +% } else { +<& /Elements/MessageBox, QuoteTransaction => $QuoteTransaction &> +%} +% $m->callback( %ARGS, QueueObj => $QueueObj, CallbackName => 'AfterMessageBox' ); + +
+
+ + <& /Elements/Submit, Label => loc("Create"), id => 'SubmitTicket' &> +
+
+ +
+ + + + + + + +
+
+ <&| /Widgets/TitleBox, title => loc('The Basics'), + title_class=> 'inverse', + color => "#993333" &> + + + + + + + + + + + + +
<&|/l&>Priority:<& /Elements/SelectPriority, + Name => "InitialPriority", + Default => $ARGS{InitialPriority} ? $ARGS{InitialPriority} : $QueueObj->InitialPriority, +&>
<&|/l&>Final Priority:<& /Elements/SelectPriority, + Name => "FinalPriority", + Default => $ARGS{FinalPriority} ? $ARGS{FinalPriority} : $QueueObj->FinalPriority, +&>
<&|/l&>Time Estimated: +<& /Elements/EditTimeValue, Name => 'TimeEstimated', Default => $ARGS{TimeEstimated} || '', InUnits => $ARGS{'TimeEstimated-TimeUnits'} &> + +
<&|/l&>Time Worked: +<& /Elements/EditTimeValue, Name => 'TimeWorked', Default => $ARGS{TimeWorked} || '', InUnits => $ARGS{'TimeWorked-TimeUnits'} &> +
<&|/l&>Time Left: +<& /Elements/EditTimeValue, Name => 'TimeLeft', Default => $ARGS{TimeLeft} || '', InUnits => $ARGS{'TimeLeft-TimeUnits'} &> +
+ +
+
+<&|/Widgets/TitleBox, title => loc("Dates"), + title_class=> 'inverse', + color => "#663366" &> + + + + +
<&|/l&>Starts:<& /Elements/SelectDate, Name => "Starts", Default => $ARGS{Starts} || '' &>
<&|/l&>Due:<& /Elements/SelectDate, Name => "Due", Default => $ARGS{Due} || '' &>
+ +
+
+
+
+ +
+ +
+<& /Elements/Submit, Label => loc("Create") &> +
+
+ +<%INIT> +$m->callback( CallbackName => "Init", ARGSRef => \%ARGS ); +my $Queue = $ARGS{Queue}; +$session{DefaultQueue} = $Queue; + +if ($CloneTicket) { + my $CloneTicketObj = RT::Ticket->new( $session{CurrentUser} ); + $CloneTicketObj->Load($CloneTicket) + or Abort( loc("Ticket could not be loaded") ); + + my $clone = { + Requestors => join( ',', $CloneTicketObj->RequestorAddresses ), + Cc => join( ',', $CloneTicketObj->CcAddresses ), + AdminCc => join( ',', $CloneTicketObj->AdminCcAddresses ), + InitialPriority => $CloneTicketObj->Priority, + }; + + $clone->{$_} = $CloneTicketObj->$_() + for qw/Owner Subject FinalPriority Status/; + # not TimeWorked, TimeEstimated, or TimeLeft + + $clone->{$_} = $CloneTicketObj->$_->AsString + for grep { $CloneTicketObj->$_->Unix } + map { $_ . "Obj" } qw/Starts Started Due Resolved/; + + my $members = $CloneTicketObj->Members; + my ( @members, @members_of, @refers, @refers_by, @depends, @depends_by ); + my $refers = $CloneTicketObj->RefersTo; + my $get_link_value = sub { + my ($link, $type) = @_; + my $uri_method = $type . 'URI'; + my $local_method = 'Local' . $type; + my $uri = $link->$uri_method; + return if $uri->IsLocal and + $uri->Object and + $uri->Object->isa('RT::Ticket') and + $uri->Object->Type eq 'reminder'; + + return $link->$local_method || $uri->URI; + }; + while ( my $refer = $refers->Next ) { + my $refer_value = $get_link_value->($refer, 'Target'); + push @refers, $refer_value if defined $refer_value; + } + $clone->{'new-RefersTo'} = join ' ', @refers; + + my $refers_by = $CloneTicketObj->ReferredToBy; + while ( my $refer_by = $refers_by->Next ) { + my $refer_by_value = $get_link_value->($refer_by, 'Base'); + push @refers_by, $refer_by_value if defined $refer_by_value; + } + $clone->{'RefersTo-new'} = join ' ', @refers_by; + + my $cfs = $CloneTicketObj->QueueObj->TicketCustomFields(); + while ( my $cf = $cfs->Next ) { + next if $cf->FirstAttribute('NoClone'); + my $cf_id = $cf->id; + my $cf_values = $CloneTicketObj->CustomFieldValues( $cf->id ); + my @cf_values; + while ( my $cf_value = $cf_values->Next ) { + push @cf_values, $cf_value->Content; + } + + if ( @cf_values > 1 && $cf->Type eq 'Select' ) { + $clone->{"Object-RT::Ticket--CustomField-$cf_id-Value"} = \@cf_values; + } + else { + $clone->{"Object-RT::Ticket--CustomField-$cf_id-Value"} = join "\n", + @cf_values; + } + } + + # Pass customer links along (even though cloning of parent links + # in general is disabled). + my $customers = $CloneTicketObj->Customers; + my @customers; + while ( my $customer = $customers->Next ) { + my ($custnum) = $customer->Target =~ /cust_main\/(\d+)$/; + push @customers, $custnum if $custnum; + } + $clone->{'new-Customer'} = join(' ', @customers); + + for ( keys %$clone ) { + $ARGS{$_} = $clone->{$_} if not defined $ARGS{$_}; + } + +} + +my @results; + +my $title = loc("Create a new ticket"); + +my $QueueObj = RT::Queue->new($session{'CurrentUser'}); +$QueueObj->Load($Queue) || Abort(loc("Queue could not be loaded.")); + +$m->callback( QueueObj => $QueueObj, title => \$title, results => \@results, ARGSRef => \%ARGS ); + +$QueueObj->Disabled && Abort(loc("Cannot create tickets in a disabled queue.")); + +my $CFs = $QueueObj->TicketCustomFields(); + +my $ValidCFs = $m->comp( + '/Elements/ValidateCustomFields', + CustomFields => $CFs, + ARGSRef => \%ARGS +); + +ProcessAttachments(ARGSRef => \%ARGS); + +my $checks_failure = 0; + +my $gnupg_widget = $m->comp('/Elements/GnuPG/SignEncryptWidget:new', Arguments => \%ARGS ); +$m->comp( '/Elements/GnuPG/SignEncryptWidget:Process', + self => $gnupg_widget, + QueueObj => $QueueObj, +); + + +if ( !exists $ARGS{'AddMoreAttach'} && ($ARGS{'id'}||'') eq 'new' ) { + my $status = $m->comp('/Elements/GnuPG/SignEncryptWidget:Check', + self => $gnupg_widget, + Operation => 'Create', + QueueObj => $QueueObj, + ); + $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 ); + +$m->comp( '/Articles/Elements/CheckSkipCreate', ARGSRef => \%ARGS, skip_create => \$skip_create, + checks_failure => $checks_failure, results => \@results ); + +if ((!exists $ARGS{'AddMoreAttach'}) and (defined($ARGS{'id'}) and $ARGS{'id'} eq 'new')) { # new ticket? + if ( $ValidCFs && !$checks_failure && !$skip_create ) { +# CREATE THE TICKET. +# For some reason it's done by a Mason component named "Display.html" +# and the call is buried in obscure error-handling stuff. +# This comment exists to make it more visually obvious. +# ************************************************************ + + $m->comp('Display.html', %ARGS); + +# ************************************************************ +# Execution should not continue here. Display.html calls +# Redirect() which does an $m->abort. We only get here if the +# code dies before then, hence "$@". + $RT::Logger->crit("After display call; error is $@"); + $m->abort(); + } + elsif ( !$ValidCFs ) { + # Invalid CFs + while (my $CF = $CFs->Next) { + my $msg = $m->notes('InvalidField-' . $CF->Id) or next; + push @results, $CF->Name . ': ' . $msg; + } + } +} +PageMenu->child( basics => raw_html => q[] . loc('Basics') . q[]); +PageMenu->child( details => raw_html => q[] . loc('Details') . q[]); + + +<%ARGS> +$DependsOn => undef +$DependedOnBy => undef +$MemberOf => undef +$QuoteTransaction => undef +$CloneTicket => undef + diff --git a/rt/share/html/Ticket/Elements/EditTransactionCustomFields b/rt/share/html/Ticket/Elements/EditTransactionCustomFields index a52ecc349..89a2fab89 100644 --- a/rt/share/html/Ticket/Elements/EditTransactionCustomFields +++ b/rt/share/html/Ticket/Elements/EditTransactionCustomFields @@ -63,8 +63,9 @@ > <<% $CELL %>> <& /Elements/EditCustomField, + %ARGS, CustomField => $CF, - NamePrefix => $NamePrefix + NamePrefix => $NamePrefix, &> % if (my $msg = $m->notes('InvalidField-' . $CF->Id)) {
diff --git a/rt/share/html/Ticket/Elements/EditTransactionCustomFields.orig b/rt/share/html/Ticket/Elements/EditTransactionCustomFields.orig new file mode 100644 index 000000000..a52ecc349 --- /dev/null +++ b/rt/share/html/Ticket/Elements/EditTransactionCustomFields.orig @@ -0,0 +1,112 @@ +%# BEGIN BPS TAGGED BLOCK {{{ +%# +%# COPYRIGHT: +%# +%# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC +%# +%# +%# (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 }}} +% $m->callback( CallbackName => 'BeforeTransactionCustomFields', TicketObj => $TicketObj, QueueObj => $QueueObj, NamePrefix => $NamePrefix ); +% if ( $WRAP ) { +<<% $WRAP %> class="edit-transaction-custom-fields"> +% } +% if ($CustomFields->Count) { +% while (my $CF = $CustomFields->Next()) { +% $CF->SetContextObject($TicketObj || $QueueObj); +% next unless $CF->CurrentUserHasRight('ModifyCustomField'); +% next unless $CF->UILocation eq $UILocation; +<<% $FIELD %>> +<<% $CELL %> class="label cflabel"> + <% loc($CF->Name) %>:
+% if ( $CF->Type ne 'TimeValue' ) { + <% $CF->FriendlyType %> +% } +> +<<% $CELL %>> +<& /Elements/EditCustomField, + CustomField => $CF, + NamePrefix => $NamePrefix +&> +% if (my $msg = $m->notes('InvalidField-' . $CF->Id)) { +
+ <% $msg %> +% } +> +> +% } +% } +% if ( $WRAP ) { +> +% } +% $m->callback( CallbackName => 'AfterTransactionCustomFields', TicketObj => $TicketObj, QueueObj => $QueueObj, NamePrefix => $NamePrefix ); + +<%INIT> +my $CustomFields; + +if ($TicketObj) { + $CustomFields = $TicketObj->TransactionCustomFields(); +} else { + $CustomFields = $QueueObj->TicketTransactionCustomFields(); +} + +$m->callback( CallbackName => 'MassageTransactionCustomFields', CustomFields => $CustomFields ); + +$AsTable ||= $InTable; +my $FIELD = $AsTable ? 'tr' : 'div'; +my $CELL = $AsTable ? 'td' : 'div'; +my $WRAP = ''; +if ( $AsTable ) { + $WRAP = 'table' unless $InTable; +} else { + $WRAP = 'div'; +} + + +<%ARGS> +$NamePrefix => "Object-RT::Transaction--CustomField-" +$TicketObj => undef +$QueueObj => undef +$AsTable => 0 +$InTable => 0 +$UILocation => '' + + diff --git a/rt/share/html/Ticket/Elements/PreviewScrips b/rt/share/html/Ticket/Elements/PreviewScrips index 3526f31a7..4067c20a3 100755 --- a/rt/share/html/Ticket/Elements/PreviewScrips +++ b/rt/share/html/Ticket/Elements/PreviewScrips @@ -88,7 +88,7 @@ my %squelched = ProcessTransactionSquelching( \%ARGS ); % } % if (RT->Config->Get('PreviewScripMessages')) { - + % }
% } diff --git a/rt/share/html/Ticket/Elements/ShowUpdateStatus b/rt/share/html/Ticket/Elements/ShowUpdateStatus index 21713a43a..43b51b578 100644 --- a/rt/share/html/Ticket/Elements/ShowUpdateStatus +++ b/rt/share/html/Ticket/Elements/ShowUpdateStatus @@ -56,10 +56,10 @@ <%ARGS> $Ticket +$DisplayPath => $session{'CurrentUser'}->Privileged ? 'Ticket' : 'SelfService' <%INIT> return unless (RT->Config->Get( 'ShowUnreadMessageNotifications', $session{'CurrentUser'})); my $txn = $Ticket->SeenUpTo or return; -my $DisplayPath = $session{'CurrentUser'}->Privileged ? 'Ticket' : 'SelfService'; diff --git a/rt/share/html/Ticket/Graphs/Elements/ShowGraph b/rt/share/html/Ticket/Graphs/Elements/ShowGraph index 1eae4b6ae..e9a5102dc 100644 --- a/rt/share/html/Ticket/Graphs/Elements/ShowGraph +++ b/rt/share/html/Ticket/Graphs/Elements/ShowGraph @@ -46,7 +46,7 @@ %# %# END BPS TAGGED BLOCK }}}
-<% safe_run_child { Encode::decode_utf8( $graph->as_cmapx ) } |n %> +<% safe_run_child { Encode::decode( "UTF-8", $graph->as_cmapx ) } |n %>
<& ShowLegends, %ARGS, Ticket => $ticket &> <%ARGS> diff --git a/rt/share/html/Ticket/ModifyAll.html b/rt/share/html/Ticket/ModifyAll.html index 6fb79e4fe..119cae400 100755 --- a/rt/share/html/Ticket/ModifyAll.html +++ b/rt/share/html/Ticket/ModifyAll.html @@ -105,7 +105,7 @@ - <& /Ticket/Elements/EditTransactionCustomFields, %ARGS, TicketObj => $Ticket &> + <& /Ticket/Elements/EditTransactionCustomFields, %ARGS, TicketObj => $Ticket, KeepValue => 1, &> <& /Ticket/Elements/AddAttachments, %ARGS, TicketObj => $Ticket &> diff --git a/rt/share/html/Ticket/Update.html b/rt/share/html/Ticket/Update.html index ae6b70095..37bb134c2 100755 --- a/rt/share/html/Ticket/Update.html +++ b/rt/share/html/Ticket/Update.html @@ -172,7 +172,7 @@ changeStatus(); % $m->callback( %ARGS, CallbackName => 'AfterWorked', Ticket => $TicketObj ); -<& /Ticket/Elements/EditTransactionCustomFields, %ARGS, TicketObj => $TicketObj, AsTable => 1 &> +<& /Ticket/Elements/EditTransactionCustomFields, %ARGS, TicketObj => $TicketObj, AsTable => 1, KeepValue => 1 &> diff --git a/rt/share/html/Ticket/Update.html.orig b/rt/share/html/Ticket/Update.html.orig new file mode 100755 index 000000000..ae6b70095 --- /dev/null +++ b/rt/share/html/Ticket/Update.html.orig @@ -0,0 +1,353 @@ +%# BEGIN BPS TAGGED BLOCK {{{ +%# +%# COPYRIGHT: +%# +%# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC +%# +%# +%# (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 }}} +<& /Elements/Header, Title => $title &> +<& /Elements/Tabs &> + +% $m->callback(CallbackName => 'BeforeActionList', ARGSRef => \%ARGS, Ticket => $TicketObj); +<& /Elements/ListActions, actions => \@results &> + +
+% $m->callback( CallbackName => 'FormStart', ARGSRef => \%ARGS, Ticket => $TicketObj, CanRespond => $CanRespond, CanComment => $CanComment, ResponseDefault => $ResponseDefault, CommentDefault => $CommentDefault ); + + + + +<& /Elements/GnuPG/SignEncryptWidget:ShowIssues, self => $gnupg_widget &> + +
+ <&|/Widgets/TitleBox, title => loc('Ticket and Transaction') &> + +% $m->callback(CallbackName => 'AfterTableOpens', ARGSRef => \%ARGS, Ticket => $TicketObj); + +<& /Ticket/Elements/EditTransactionCustomFields, + %ARGS, + TicketObj => $TicketObj, + UILocation => 'TimeWorked', +&> + +% my $skip; +% $m->callback( %ARGS, CallbackName => 'BeforeUpdateType', skip => \$skip ); +% if (!$skip) { +
+% } + + + + + +<& /Ticket/Elements/EditBasics, + TicketObj => $TicketObj, + InTable => 1, + fields => [ + { name => 'Status', + comp => '/Elements/SelectStatus', + args => { + Name => 'Status', + DefaultLabel => loc("[_1] (Unchanged)", loc($TicketObj->Status)), + Default => $ARGS{'Status'} || ($TicketObj->Status eq $DefaultStatus ? undef : $DefaultStatus), + TicketObj => $TicketObj, + QueueObj => $TicketObj->QueueObj, + onchange => 'changeStatus()' + }, + }, + { name => 'Resolve this Ticket on', + comp => '/Elements/SelectDate', + args => { + menu_prefix => 'WillResolve', + current => 0, + ShowTime => 0, + }, + }, + { name => 'Owner', + comp => '/Elements/SelectOwner', + args => { + Name => "Owner", + TicketObj => $TicketObj, + QueueObj => $TicketObj->QueueObj, + DefaultLabel => loc("[_1] (Unchanged)", $m->scomp('/Elements/ShowUser', User => $TicketObj->OwnerObj)), + Default => $ARGS{'Owner'} + } + }, + { name => 'Worked', + comp => '/Elements/EditTimeValue', + args => { + Name => 'UpdateTimeWorked', + Default => $ARGS{UpdateTimeWorked}||'', + InUnits => $ARGS{'UpdateTimeWorked-TimeUnits'}||'minutes', + } + }, + ] +&> + + + +% $m->callback( %ARGS, CallbackName => 'AfterWorked', Ticket => $TicketObj ); + +<& /Ticket/Elements/EditTransactionCustomFields, %ARGS, TicketObj => $TicketObj, AsTable => 1 &> + + + + + +
+ <& /Ticket/Elements/ShowSimplifiedRecipients, TicketObj => $TicketObj, %ARGS &> + + <&|/Widgets/TitleBox, title => loc('Message'), class => 'messagedetails' &> +
<&|/l&>Update Type: + + + +% $m->callback( %ARGS, CallbackName => 'AfterUpdateType' ); +
+<& /Ticket/Elements/UpdateCc, %ARGS, TicketObj => $TicketObj &> + +% if ( $gnupg_widget ) { + +% } +% $m->callback( %ARGS, CallbackName => 'AfterGnuPG' ); + + + + + + + <& /Ticket/Elements/AddAttachments, %ARGS, TicketObj => $TicketObj &> +
  +<& /Elements/GnuPG/SignEncryptWidget, + self => $gnupg_widget, + TicketObj => $TicketObj, +&> +
<&|/l&>Subject: +% $m->callback( %ARGS, CallbackName => 'AfterSubject' ); +
<&|/l&>Message: +<& /Articles/Elements/BeforeMessageBox, %ARGS &> +% $m->callback( %ARGS, CallbackName => 'BeforeMessageBox' ); +% if (exists $ARGS{UpdateContent}) { +% # preserve QuoteTransaction so we can use it to set up sane references/in/reply to +% my $temp = $ARGS{'QuoteTransaction'}; +% delete $ARGS{'QuoteTransaction'}; +<& /Elements/MessageBox, Name=>"UpdateContent", Default=>$ARGS{UpdateContent}, IncludeSignature => 0, %ARGS&> +% $ARGS{'QuoteTransaction'} = $temp; +% } else { +% my $IncludeSignature = 1; +% $IncludeSignature = 0 if $Action ne 'Respond' && !RT->Config->Get('MessageBoxIncludeSignatureOnComment'); +<& /Elements/MessageBox, Name=>"UpdateContent", IncludeSignature => $IncludeSignature, %ARGS &> +% } +% $m->callback( %ARGS, CallbackName => 'AfterMessageBox' ); +
+ + +% $m->callback( %ARGS, CallbackName => 'BeforeSubmit', Ticket => $TicketObj ); + + <& /Elements/Submit, Label => loc('Update Ticket'), Name => 'SubmitTicket', id => 'SubmitTicket' &> + +% $m->callback( %ARGS, CallbackName => 'BeforeScrips', Ticket => $TicketObj ); + +% if ($TicketObj->CurrentUserHasRight('ShowOutgoingEmail')) { + <&|/Widgets/TitleBox, title => loc('Scrips and Recipients'), id => 'previewscrips', rolledup => RT->Config->Get('SimplifiedRecipients', $session{'CurrentUser'}) &> + <& /Ticket/Elements/PreviewScrips, TicketObj => $TicketObj, %ARGS &> + +% } +
+ +% $m->callback( %ARGS, CallbackName => 'AfterScrips', Ticket => $TicketObj ); + +% if (my $recips = $m->notes("DryRun-Recipients-".$TicketObj->Id)) { +" /> +% } + +
+
+ +% $m->callback( %ARGS, CallbackName => 'AfterForm', Ticket => $TicketObj ); + +<%INIT> +my $CanRespond = 0; +my $CanComment = 0; +my $checks_failure = 0; + +my $TicketObj = LoadTicket($id); + +my @results; + +$m->callback( Ticket => $TicketObj, ARGSRef => \%ARGS, checks_failure => \$checks_failure, results => \@results, CallbackName => 'Initial' ); + +unless($DefaultStatus){ + $DefaultStatus=($ARGS{'Status'} ||$TicketObj->Status()); +} + +my $title = loc("Update ticket #[_1] ([_2])", $TicketObj->id, $TicketObj->Subject||''); + +# Things needed in the template - we'll do the processing here, just +# for the convenience: + +my ($CommentDefault, $ResponseDefault); +if ($Action ne 'Respond') { + $CommentDefault = qq[ selected="selected"]; + $ResponseDefault = ""; +} else { + $CommentDefault = ""; + $ResponseDefault = qq[ selected="selected"]; +} + +my $type = $ARGS{'UpdateType'} ? $ARGS{'UpdateType'} : + lc $ARGS{'Action'} eq 'respond' ? 'response' : + lc $ARGS{'Action'} eq 'comment' ? 'private' : + 'none' ; + + +$CanRespond = 1 if ( $TicketObj->CurrentUserHasRight('ReplyToTicket') or + $TicketObj->CurrentUserHasRight('ModifyTicket') ); + +$CanComment = 1 if ( $TicketObj->CurrentUserHasRight('CommentOnTicket') or + $TicketObj->CurrentUserHasRight('ModifyTicket') ); + + +ProcessAttachments(ARGSRef => \%ARGS); + +my $gnupg_widget = $m->comp('/Elements/GnuPG/SignEncryptWidget:new', Arguments => \%ARGS ); +$m->comp( '/Elements/GnuPG/SignEncryptWidget:Process', + self => $gnupg_widget, + TicketObj => $TicketObj, +); + +if ( $ARGS{'SubmitTicket'} ) { + + my %squelched = ProcessTransactionSquelching( \%ARGS ); + $ARGS{'SquelchMailTo'} = [keys %squelched] if keys %squelched; + + my $CFs = $TicketObj->TransactionCustomFields; + my $ValidCFs = $m->comp( + '/Elements/ValidateCustomFields', + CustomFields => $CFs, + NamePrefix => "Object-RT::Transaction--CustomField-", + ARGSRef => \%ARGS + ); + unless ( $ValidCFs ) { + $checks_failure = 1; + while (my $CF = $CFs->Next) { + my $msg = $m->notes('InvalidField-' . $CF->Id) or next; + push @results, loc($CF->Name) . ': ' . $msg; + } + } + my $status = $m->comp('/Elements/GnuPG/SignEncryptWidget:Check', + self => $gnupg_widget, + TicketObj => $TicketObj, + ); + $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; + } +} +my $skip_update = 0; +$m->callback( CallbackName => 'BeforeUpdate', ARGSRef => \%ARGS, skip_update => \$skip_update, + checks_failure => $checks_failure, results => \@results, TicketObj => $TicketObj ); + +if ( !$checks_failure && !$skip_update && exists $ARGS{SubmitTicket} ) { + $m->callback( Ticket => $TicketObj, ARGSRef => \%ARGS, CallbackName => 'BeforeDisplay' ); + return $m->comp('Display.html', TicketObj => $TicketObj, %ARGS); +} + + +<%ARGS> +$id => undef +$Action => undef +$DefaultStatus => undef + diff --git a/rt/share/html/Tools/Offline.html b/rt/share/html/Tools/Offline.html index 507ca17e2..de49e00c8 100644 --- a/rt/share/html/Tools/Offline.html +++ b/rt/share/html/Tools/Offline.html @@ -114,7 +114,6 @@ if ($ARGS{'Parse'} && $ARGS{'Template'}) { $template .= $buffer; } my $encode = RT::I18N::_GuessCharset( $template ); - require Encode; $template = Encode::decode( $encode, $template ); $template =~ s/\r\n/\n/gs; $action->Parse(Content => $template, Queue => $qname, Requestor => $requestoraddress); diff --git a/rt/share/html/Widgets/TitleBoxStart b/rt/share/html/Widgets/TitleBoxStart index f6655edad..4982315fe 100755 --- a/rt/share/html/Widgets/TitleBoxStart +++ b/rt/share/html/Widgets/TitleBoxStart @@ -81,7 +81,7 @@ $hideable = 1 if $rolledup; # my $page = $m->request_comp->path; -my $title_b64 = MIME::Base64::encode_base64(Encode::encode_utf8($title), ''); +my $title_b64 = MIME::Base64::encode_base64(Encode::encode( "UTF-8", $title), ''); my $tid = "TitleBox--$page--" . join '--', ($class, $bodyclass, $title_b64, $id); -- cgit v1.2.1