[otrs-cvs] ITSMIncidentProblemManagement/Kernel/Modules AgentTicketActionCommon.pm, 1.33, 1.34 AgentTicketPrint.pm, 1.11, 1.12 AgentTicketPhone.pm, 1.49, 1.50 AgentTicketEmail.pm, 1.44, 1.45 CustomerTicketPrint.pm, 1.10, 1.11 AgentTicketZoom.pm, 1.36, 1.37

"CVS commits notifications of OTRS.org" <[email protected]>
Newsgroups gmane.comp.otrs.cvs
Message-ID <[email protected]>
Comments:
Update of /home/cvs/ITSMIncidentProblemManagement/Kernel/Modules
In directory lancelot:/tmp/cvs-serv24829/Kernel/Modules

Modified Files:
	AgentTicketActionCommon.pm AgentTicketPrint.pm 
	AgentTicketPhone.pm AgentTicketEmail.pm CustomerTicketPrint.pm 
	AgentTicketZoom.pm 
Log Message:
Updated files to the latest framework version.

Author: ub

Index: AgentTicketActionCommon.pm
===================================================================
RCS file: /home/cvs/ITSMIncidentProblemManagement/Kernel/Modules/AgentTicketActionCommon.pm,v
retrieving revision 1.33
retrieving revision 1.34
diff -2 -u -d -r1.33 -r1.34
--- AgentTicketActionCommon.pm	2 Oct 2012 11:02:03 -0000	1.33
+++ AgentTicketActionCommon.pm	22 Nov 2012 13:50:27 -0000	1.34
@@ -4,5 +4,5 @@
 # --
 # $Id$
-# $OldId: AgentTicketActionCommon.pm,v 1.81.2.9 2012/09/24 09:28:05 mg Exp $
+# $OldId: AgentTicketActionCommon.pm,v 1.102 2012/11/20 14:47:30 mh Exp $
 # --
 # This software comes with ABSOLUTELY NO WARRANTY. For details, see
@@ -226,5 +226,5 @@
     for my $Key (
         qw(
-        NewStateID NewPriorityID TimeUnits ArticleTypeID Title Body Subject
+        NewStateID NewPriorityID TimeUnits ArticleTypeID Title Body Subject NewQueueID
         Year Month Day Hour Minute NewOwnerID NewOwnerType OldOwnerID NewResponsibleID
         TypeID ServiceID SLAID Expand
@@ -353,5 +353,5 @@
     my %DynamicFieldACLParameters;
     DYNAMICFIELD:
-    for my $DynamicField ( keys %DynamicFieldValues ) {
+    for my $DynamicField ( sort keys %DynamicFieldValues ) {
         next DYNAMICFIELD if !$DynamicField;
         next DYNAMICFIELD if !$DynamicFieldValues{$DynamicField};
@@ -542,4 +542,8 @@
             if ( IsHashRefWithData( $DynamicFieldConfig->{Config}->{PossibleValues} ) ) {
 
+                # convert possible values key => value to key => key for ACLs usign a Hash slice
+                my %AclData = %{ $DynamicFieldConfig->{Config}->{PossibleValues} };
+                @AclData{ keys %AclData } = keys %AclData;
+
                 # set possible values filter from ACLs
                 my $ACL = $Self->{TicketObject}->TicketAcl(
@@ -549,10 +553,14 @@
                     ReturnType    => 'Ticket',
                     ReturnSubType => 'DynamicField_' . $DynamicFieldConfig->{Name},
-                    Data          => $DynamicFieldConfig->{Config}->{PossibleValues},
+                    Data          => \%AclData,
                     UserID        => $Self->{UserID},
                 );
                 if ($ACL) {
                     my %Filter = $Self->{TicketObject}->TicketAclData();
-                    $PossibleValuesFilter = \%Filter;
+
+                    # convert Filer key => key back to key => value using map
+                    %{$PossibleValuesFilter}
+                        = map { $_ => $DynamicFieldConfig->{Config}->{PossibleValues}->{$_} }
+                        keys %Filter;
                 }
             }
@@ -731,7 +739,43 @@
         }
 
+        # move ticket to a new queue, but only if the queue was changed
+        if (
+            $Self->{Config}->{Queue}
+            && $GetParam{NewQueueID}
+            && $GetParam{NewQueueID} ne $Ticket{QueueID}
+            )
+        {
+
+            # move ticket (send notification if no new owner is selected)
+            my $BodyAsText = '';
+            if ( $Self->{LayoutObject}->{BrowserRichText} ) {
+                $BodyAsText = $Self->{LayoutObject}->RichText2Ascii(
+                    String => $GetParam{Body} || 0,
+                );
+            }
+            else {
+                $BodyAsText = $GetParam{Body} || 0;
+            }
+            my $Move = $Self->{TicketObject}->TicketQueueSet(
+                QueueID            => $GetParam{NewQueueID},
+                UserID             => $Self->{UserID},
+                TicketID           => $Self->{TicketID},
+                SendNoNotification => $GetParam{NewUserID},
+                Comment            => $BodyAsText,
+            );
+            if ( !$Move ) {
+                return $Self->{LayoutObject}->ErrorScreen();
+            }
+        }
+
         # add note
         my $ArticleID = '';
         if ( $Self->{Config}->{Note} ) {
+
+            # if there is no ArticleTypeID, use the default value
+            if ( !defined $GetParam{ArticleTypeID} ) {
+                $GetParam{ArticleType} = $Self->{Config}->{ArticleTypeDefault};
+            }
+
             my $MimeType = 'text/plain';
             if ( $Self->{LayoutObject}->{BrowserRichText} ) {
@@ -928,10 +972,10 @@
         }
 
-        my $QueueID = $Ticket{QueueID};
+        my $QueueID = $GetParam{NewQueueID} || $Ticket{QueueID};
 
         # convert dynamic field values into a structure for ACLs
         my %DynamicFieldACLParameters;
         DYNAMICFIELD:
-        for my $DynamicField ( keys %DynamicFieldValues ) {
+        for my $DynamicField ( sort keys %DynamicFieldValues ) {
             next DYNAMICFIELD if !$DynamicField;
             next DYNAMICFIELD if !$DynamicFieldValues{$DynamicField};
@@ -972,5 +1016,5 @@
 
         # reset previous ServiceID to reset SLA-List if no service is selected
-        if ( !$Services->{$ServiceID} ) {
+        if ( !defined $ServiceID || !$Services->{$ServiceID} ) {
             $ServiceID = '';
         }
@@ -984,8 +1028,8 @@
             %GetParam,
             CustomerUserID => $CustomerUser || '',
-            QueueID        => $QueueID      || 1,
+            QueueID => $QueueID,
         );
 
-        # update Dynamc Fields Possible Values via AJAX
+        # update Dynamic Fields Possible Values via AJAX
         my @DynamicFieldAJAX;
 
@@ -1004,17 +1048,23 @@
             );
 
+            # convert possible values key => value to key => key for ACLs usign a Hash slice
+            my %AclData = %{$PossibleValues};
+            @AclData{ keys %AclData } = keys %AclData;
+
             # set possible values filter from ACLs
             my $ACL = $Self->{TicketObject}->TicketAcl(
                 %GetParam,
                 Action        => $Self->{Action},
-                QueueID       => $QueueID || 0,
+                QueueID       => $QueueID,
                 ReturnType    => 'Ticket',
                 ReturnSubType => 'DynamicField_' . $DynamicFieldConfig->{Name},
-                Data          => $PossibleValues,
+                Data          => \%AclData,
                 UserID        => $Self->{UserID},
             );
             if ($ACL) {
                 my %Filter = $Self->{TicketObject}->TicketAclData();
-                $PossibleValues = \%Filter;
+
+                # convert Filer key => key back to key => value using map
+                %{$PossibleValues} = map { $_ => $PossibleValues->{$_} } keys %Filter;
             }
 
@@ -1031,4 +1081,5 @@
             );
         }
+
         my $JSON = $Self->{LayoutObject}->BuildSelectionJSON(
             [
@@ -1135,4 +1186,8 @@
             if ( IsHashRefWithData( $DynamicFieldConfig->{Config}->{PossibleValues} ) ) {
 
+                # convert possible values key => value to key => key for ACLs usign a Hash slice
+                my %AclData = %{ $DynamicFieldConfig->{Config}->{PossibleValues} };
+                @AclData{ keys %AclData } = keys %AclData;
+
                 # set possible values filter from ACLs
                 my $ACL = $Self->{TicketObject}->TicketAcl(
@@ -1142,10 +1197,14 @@
                     ReturnType    => 'Ticket',
                     ReturnSubType => 'DynamicField_' . $DynamicFieldConfig->{Name},
-                    Data          => $DynamicFieldConfig->{Config}->{PossibleValues},
+                    Data          => \%AclData,
                     UserID        => $Self->{UserID},
                 );
                 if ($ACL) {
                     my %Filter = $Self->{TicketObject}->TicketAclData();
-                    $PossibleValuesFilter = \%Filter;
+
+                    # convert Filer key => key back to key => value using map
+                    %{$PossibleValuesFilter}
+                        = map { $_ => $DynamicFieldConfig->{Config}->{PossibleValues}->{$_} }
+                        keys %Filter;
                 }
             }
@@ -1306,4 +1365,31 @@
         );
     }
+
+    if ( $Self->{Config}->{Queue} ) {
+
+        # fetch all queues
+        my %MoveQueues = $Self->{TicketObject}->TicketMoveList(
+            TicketID => $Self->{TicketID},
+            UserID   => $Self->{UserID},
+            Action   => $Self->{Action},
+            Type     => 'move_into',
+        );
+
+        $Param{QueuesStrg} = $Self->{LayoutObject}->BuildSelection(
+            Data         => \%MoveQueues,
+            Name         => 'NewQueueID',
+            SelectedID   => $Param{NewQueueID},
+            PossibleNone => 0,
+            TreeView     => 1,
+            Sort         => 'TreeView',
+            Translation  => 0,
+        );
+
+        $Self->{LayoutObject}->Block(
+            Name => 'Queue',
+            Data => {%Param},
+        );
+    }
+
     if ( $Self->{Config}->{Owner} ) {
 
@@ -1325,5 +1411,5 @@
                 Cached  => 1,
             );
-            for my $UserID ( keys %MemberList ) {
+            for my $UserID ( sort keys %MemberList ) {
                 $ShownUsers{$UserID} = $AllGroupsMembers{$UserID};
             }
@@ -1350,4 +1436,5 @@
             }
         }
+
         my $OldOwnerSelectedID = '';
         if ( $Param{OldOwnerID} ) {
@@ -1397,5 +1484,5 @@
                 Cached  => 1,
             );
-            for my $UserID ( keys %MemberList ) {
+            for my $UserID ( sort keys %MemberList ) {
                 $ShownUsers{$UserID} = $AllGroupsMembers{$UserID};
             }
@@ -1404,8 +1491,9 @@
         # get responsible
         $Param{ResponsibleStrg} = $Self->{LayoutObject}->BuildSelection(
-            Data       => \%ShownUsers,
-            SelectedID => $Param{NewResponsibleID} || $Ticket{ResponsibleID},
-            Name       => 'NewResponsibleID',
-            Size       => 1,
+            Data         => \%ShownUsers,
+            SelectedID   => $Param{NewResponsibleID} || $Ticket{ResponsibleID},
+            Name         => 'NewResponsibleID',
+            PossibleNone => 1,
+            Size         => 1,
         );
         $Self->{LayoutObject}->Block(
@@ -1511,4 +1599,9 @@
         # add rich text editor
         if ( $Self->{LayoutObject}->{BrowserRichText} ) {
+
+            # use height/width defined for this screen
+            $Param{RichTextHeight} = $Self->{Config}->{RichTextHeight} || 0;
+            $Param{RichTextWidth}  = $Self->{Config}->{RichTextWidth}  || 0;
+
             $Self->{LayoutObject}->Block(
                 Name => 'RichText',
@@ -1531,5 +1624,5 @@
                 Cached  => 1,
             );
-            for my $UserID ( keys %MemberList ) {
+            for my $UserID ( sort keys %MemberList ) {
                 $ShownUsers{$UserID} = $AllGroupsMembers{$UserID};
             }
@@ -1618,20 +1711,23 @@
 
         # get possible notes
-        my %DefaultNoteTypes = %{ $Self->{Config}->{ArticleTypes} };
-        my %NoteTypes = $Self->{TicketObject}->ArticleTypeList( Result => 'HASH' );
-        for my $KeyNoteType ( keys %NoteTypes ) {
-            if ( !$DefaultNoteTypes{ $NoteTypes{$KeyNoteType} } ) {
-                delete $NoteTypes{$KeyNoteType};
+        if ( $Self->{Config}->{ArticleTypes} ) {
+            my %DefaultNoteTypes = %{ $Self->{Config}->{ArticleTypes} };
+            my %NoteTypes = $Self->{TicketObject}->ArticleTypeList( Result => 'HASH' );
+            for my $KeyNoteType ( sort keys %NoteTypes ) {
+                if ( !$DefaultNoteTypes{ $NoteTypes{$KeyNoteType} } ) {
+                    delete $NoteTypes{$KeyNoteType};
+                }
             }
+
+            $Param{ArticleTypeStrg} = $Self->{LayoutObject}->BuildSelection(
+                Data => \%NoteTypes,
+                Name => 'ArticleTypeID',
+                %ArticleType,
+            );
+            $Self->{LayoutObject}->Block(
+                Name => 'ArticleType',
+                Data => \%Param,
+            );
         }
-        $Param{ArticleTypeStrg} = $Self->{LayoutObject}->BuildSelection(
-            Data => \%NoteTypes,
-            Name => 'ArticleTypeID',
-            %ArticleType,
-        );
-        $Self->{LayoutObject}->Block(
-            Name => 'ArticleType',
-            Data => \%Param,
-        );
 
         # show time accounting box
@@ -1751,5 +1847,7 @@
     );
     if ( $Param{QueueID} && !$Param{AllUsers} ) {
-        my $GID = $Self->{QueueObject}->GetQueueGroupID( QueueID => $Param{QueueID} );
+        my $GID = $Self->{QueueObject}->GetQueueGroupID(
+            QueueID => $Param{NewQueueID} || $Param{QueueID}
+        );
         my %MemberList = $Self->{GroupObject}->GroupMemberList(
             GroupID => $GID,
@@ -1758,5 +1856,5 @@
             Cached  => 1,
         );
-        for my $UserID ( keys %MemberList ) {
+        for my $UserID ( sort keys %MemberList ) {
             $ShownUsers{$UserID} = $AllGroupsMembers{$UserID};
         }
@@ -1785,5 +1883,7 @@
     );
     if ( $Param{QueueID} && !$Param{AllUsers} ) {
-        my $GID = $Self->{QueueObject}->GetQueueGroupID( QueueID => $Param{QueueID} );
+        my $GID = $Self->{QueueObject}->GetQueueGroupID(
+            QueueID => $Param{NewQueueID} || $Param{QueueID}
+        );
         my %MemberList = $Self->{GroupObject}->GroupMemberList(
             GroupID => $GID,
@@ -1792,5 +1892,5 @@
             Cached  => 1,
         );
-        for my $UserID ( keys %MemberList ) {
+        for my $UserID ( sort keys %MemberList ) {
             $ShownUsers{$UserID} = $AllGroupsMembers{$UserID};
         }

Author: ub

Index: AgentTicketPrint.pm
===================================================================
RCS file: /home/cvs/ITSMIncidentProblemManagement/Kernel/Modules/AgentTicketPrint.pm,v
retrieving revision 1.11
retrieving revision 1.12
diff -2 -u -d -r1.11 -r1.12
--- AgentTicketPrint.pm	23 Jun 2012 12:09:49 -0000	1.11
+++ AgentTicketPrint.pm	22 Nov 2012 13:50:27 -0000	1.12
@@ -4,5 +4,5 @@
 # --
 # $Id$
-# $OldId: AgentTicketPrint.pm,v 1.86 2012/01/24 00:08:45 cr Exp $
+# $OldId: AgentTicketPrint.pm,v 1.91 2012/11/20 14:51:07 mh Exp $
 # --
 # This software comes with ABSOLUTELY NO WARRANTY. For details, see
@@ -188,7 +188,10 @@
     }
 
-    $Ticket{TicketTimeUnits} = $Self->{TicketObject}->TicketAccountedTimeGet(
-        TicketID => $Ticket{TicketID},
-    );
+    # show total accounted time if feature is active:
+    if ( $Self->{ConfigObject}->Get('Ticket::Frontend::AccountTime') ) {
+        $Ticket{TicketTimeUnits} = $Self->{TicketObject}->TicketAccountedTimeGet(
+            TicketID => $Ticket{TicketID},
+        );
+    }
 
     # user info
@@ -230,7 +233,4 @@
         );
     }
-    else {
-        $Ticket{PendingUntil} = '-';
-    }
 
     # generate pdf output
@@ -556,13 +556,22 @@
             ),
         },
-        {
+    ];
+
+    if ( $Self->{ConfigObject}->Get('Ticket::Frontend::AccountTime') ) {
+        my $Row = {
             Key   => $Self->{LayoutObject}->{LanguageObject}->Get('Accounted time') . ':',
             Value => $Ticket{TicketTimeUnits},
-        },
-        {
+        };
+        push( @{$TableRight}, $Row );
+    }
+
+    # only show pending until unless it is really pending
+    if ( $Ticket{PendingUntil} ) {
+        my $Row = {
             Key   => $Self->{LayoutObject}->{LanguageObject}->Get('Pending till') . ':',
             Value => $Ticket{PendingUntil},
-        },
-    ];
+        };
+        push( @{$TableRight}, $Row );
+    }
 
     # add first response time row
@@ -1002,12 +1011,15 @@
         }
         my $Attachments;
-        for my $FileID ( keys %AtmIndex ) {
+        for my $FileID ( sort keys %AtmIndex ) {
             my %File = %{ $AtmIndex{$FileID} };
             $Attachments .= $File{Filename} . ' (' . $File{Filesize} . ")\n";
         }
 
-        $Article{'Accounted time'} = $Self->{TicketObject}->ArticleAccountedTimeGet(
-            ArticleID => $Article{ArticleID},
-        );
+        # show total accounted time if feature is active:
+        if ( $Self->{ConfigObject}->Get('Ticket::Frontend::AccountTime') ) {
+            $Article{'Accounted time'} = $Self->{TicketObject}->ArticleAccountedTimeGet(
+                ArticleID => $Article{ArticleID},
+            );
+        }
 
         # generate article info table
@@ -1213,4 +1225,20 @@
     }
 
+    # output accounted time
+    if ( $Self->{ConfigObject}->Get('Ticket::Frontend::AccountTime') ) {
+        $Self->{LayoutObject}->Block(
+            Name => 'AccountedTime',
+            Data => {%Param},
+        );
+    }
+
+    # output pending date
+    if ( $Param{PendingUntil} ) {
+        $Self->{LayoutObject}->Block(
+            Name => 'PendingUntil',
+            Data => {%Param},
+        );
+    }
+
     # output first response time
     if ( defined( $Param{FirstResponseTime} ) ) {
@@ -1302,12 +1330,11 @@
         }
         $Param{'Article::ATM'} = '';
-        for my $FileID ( keys %AtmIndex ) {
+        for my $FileID ( sort keys %AtmIndex ) {
             my %File = %{ $AtmIndex{$FileID} };
             $File{Filename} = $Self->{LayoutObject}->Ascii2Html( Text => $File{Filename} );
             $Param{'Article::ATM'}
-                .= '<a href="$Env{"CGIHandle"}/$QData{"Filename"}?Action=AgentTicketAttachment&'
+                .= '<a href="$Env{"Baselink"}Action=AgentTicketAttachment;'
                 . "ArticleID=$Article{ArticleID};FileID=$FileID\" target=\"attachment\" "
-                . "onmouseover=\"window.status='\$Text{\"Download\"}: $File{Filename}';"
-                . ' return true;" onmouseout="window.status=\'\';">'
+                . "title=\"\$Text{\"Download\"}: $File{Filename}\">"
                 . "$File{Filename}</a> $File{Filesize}<br/>";
         }

Author: ub

Index: AgentTicketPhone.pm
===================================================================
RCS file: /home/cvs/ITSMIncidentProblemManagement/Kernel/Modules/AgentTicketPhone.pm,v
retrieving revision 1.49
retrieving revision 1.50
diff -2 -u -d -r1.49 -r1.50
--- AgentTicketPhone.pm	22 Oct 2012 21:24:53 -0000	1.49
+++ AgentTicketPhone.pm	22 Nov 2012 13:50:27 -0000	1.50
@@ -4,5 +4,5 @@
 # --
 # $Id$
-# $OldId: AgentTicketPhone.pm,v 1.236.2.8 2012/10/11 20:02:41 cr Exp $
+# $OldId: AgentTicketPhone.pm,v 1.249 2012/11/20 14:50:19 mh Exp $
 # --
 # This software comes with ABSOLUTELY NO WARRANTY. For details, see
@@ -217,5 +217,5 @@
     my %DynamicFieldACLParameters;
     DYNAMICFIELD:
-    for my $DynamicField ( keys %DynamicFieldValues ) {
+    for my $DynamicField ( sort keys %DynamicFieldValues ) {
         next DYNAMICFIELD if !$DynamicField;
         next DYNAMICFIELD if !$DynamicFieldValues{$DynamicField};
@@ -524,5 +524,5 @@
                 = $SplitTicketData{QueueID} . '||' . $SplitTicketData{Queue};
 
-            for my $Key ( keys %SplitTicketData ) {
+            for my $Key ( sort keys %SplitTicketData ) {
                 if ( $Key =~ /DynamicField\_(.*)/ ) {
                     $SplitTicketParam{DynamicField}{$1} = $SplitTicketData{$Key};
@@ -542,4 +542,8 @@
             if ( IsHashRefWithData( $DynamicFieldConfig->{Config}->{PossibleValues} ) ) {
 
+                # convert possible values key => value to key => key for ACLs usign a Hash slice
+                my %AclData = %{ $DynamicFieldConfig->{Config}->{PossibleValues} };
+                @AclData{ keys %AclData } = keys %AclData;
+
                 # set possible values filter from ACLs
                 my $ACL = $Self->{TicketObject}->TicketAcl(
@@ -550,10 +554,14 @@
                     ReturnType    => 'Ticket',
                     ReturnSubType => 'DynamicField_' . $DynamicFieldConfig->{Name},
-                    Data          => $DynamicFieldConfig->{Config}->{PossibleValues},
+                    Data          => \%AclData,
                     UserID        => $Self->{UserID},
                 );
                 if ($ACL) {
                     my %Filter = $Self->{TicketObject}->TicketAclData();
-                    $PossibleValuesFilter = \%Filter;
+
+                    # convert Filer key => key back to key => value using map
+                    %{$PossibleValuesFilter}
+                        = map { $_ => $DynamicFieldConfig->{Config}->{PossibleValues}->{$_} }
+                        keys %Filter;
                 }
             }
@@ -837,4 +845,8 @@
             if ( IsHashRefWithData( $DynamicFieldConfig->{Config}->{PossibleValues} ) ) {
 
+                # convert possible values key => value to key => key for ACLs usign a Hash slice
+                my %AclData = %{ $DynamicFieldConfig->{Config}->{PossibleValues} };
+                @AclData{ keys %AclData } = keys %AclData;
+
                 # set possible values filter from ACLs
                 my $ACL = $Self->{TicketObject}->TicketAcl(
@@ -843,10 +855,14 @@
                     ReturnType    => 'Ticket',
                     ReturnSubType => 'DynamicField_' . $DynamicFieldConfig->{Name},
-                    Data          => $DynamicFieldConfig->{Config}->{PossibleValues},
+                    Data          => \%AclData,
                     UserID        => $Self->{UserID},
                 );
                 if ($ACL) {
                     my %Filter = $Self->{TicketObject}->TicketAclData();
-                    $PossibleValuesFilter = \%Filter;
+
+                    # convert Filer key => key back to key => value using map
+                    %{$PossibleValuesFilter}
+                        = map { $_ => $DynamicFieldConfig->{Config}->{PossibleValues}->{$_} }
+                        keys %Filter;
                 }
             }
@@ -907,5 +923,5 @@
             # if just one, fillup CustomerUserID and CustomerID
             $Param{CustomerUserListCount} = 0;
-            for my $KeyCustomerUser ( keys %CustomerUserList ) {
+            for my $KeyCustomerUser ( sort keys %CustomerUserList ) {
                 $Param{CustomerUserListCount}++;
                 $Param{CustomerUserListLast}     = $CustomerUserList{$KeyCustomerUser};
@@ -950,5 +966,5 @@
                 UserLogin => $CustomerUser,
             );
-            for my $KeyCustomerUser ( keys %CustomerUserList ) {
+            for my $KeyCustomerUser ( sort keys %CustomerUserList ) {
                 $GetParam{From} = $CustomerUserList{$KeyCustomerUser};
             }
@@ -1477,5 +1493,5 @@
 
         if ($Tos) {
-            for my $KeyTo ( keys %{$Tos} ) {
+            for my $KeyTo ( sort keys %{$Tos} ) {
                 $NewTos->{"$KeyTo||$Tos->{$KeyTo}"} = $Tos->{$KeyTo};
             }
@@ -1536,4 +1552,8 @@
             );
 
+            # convert possible values key => value to key => key for ACLs usign a Hash slice
+            my %AclData = %{$PossibleValues};
+            @AclData{ keys %AclData } = keys %AclData;
+
             # set possible values filter from ACLs
             my $ACL = $Self->{TicketObject}->TicketAcl(
@@ -1544,10 +1564,12 @@
                 ReturnType    => 'Ticket',
                 ReturnSubType => 'DynamicField_' . $DynamicFieldConfig->{Name},
-                Data          => $PossibleValues,
+                Data          => \%AclData,
                 UserID        => $Self->{UserID},
             );
             if ($ACL) {
                 my %Filter = $Self->{TicketObject}->TicketAclData();
-                $PossibleValues = \%Filter;
+
+                # convert Filer key => key back to key => value using map
+                %{$PossibleValues} = map { $_ => $PossibleValues->{$_} } keys %Filter;
             }
 
@@ -1668,5 +1690,5 @@
     if ( $Param{QueueID} && !$Param{AllUsers} ) {
         my @UserIDs = $Self->{TicketObject}->GetSubscribedUserIDsByQueueID(%Param);
-        for my $KeyGroupMember ( keys %AllGroupsMembers ) {
+        for my $KeyGroupMember ( sort keys %AllGroupsMembers ) {
             my $Hit = 0;
             for my $UID (@UserIDs) {
@@ -1694,5 +1716,5 @@
             Result  => 'HASH',
         );
-        for my $KeyMember ( keys %MemberList ) {
+        for my $KeyMember ( sort keys %MemberList ) {
             if ( $AllGroupsMembers{$KeyMember} ) {
                 $ShownUsers{$KeyMember} = $AllGroupsMembers{$KeyMember};
@@ -1728,5 +1750,5 @@
     if ( $Param{QueueID} && !$Param{AllUsers} ) {
         my @UserIDs = $Self->{TicketObject}->GetSubscribedUserIDsByQueueID(%Param);
-        for my $KeyGroupMember ( keys %AllGroupsMembers ) {
+        for my $KeyGroupMember ( sort keys %AllGroupsMembers ) {
             my $Hit = 0;
             for my $UID (@UserIDs) {
@@ -1754,5 +1776,5 @@
             Result  => 'HASH',
         );
-        for my $KeyMember ( keys %MemberList ) {
+        for my $KeyMember ( sort keys %MemberList ) {
             if ( $AllGroupsMembers{$KeyMember} ) {
                 $ShownUsers{$KeyMember} = $AllGroupsMembers{$KeyMember};
@@ -1884,5 +1906,5 @@
 
         # build selection string
-        for my $QueueID ( keys %Tos ) {
+        for my $QueueID ( sort keys %Tos ) {
             my %QueueData = $Self->{QueueObject}->QueueGet( ID => $QueueID );
 
@@ -1955,5 +1977,5 @@
     my %NewTo;
     if ( $Param{To} ) {
-        for my $KeyTo ( keys %{ $Param{To} } ) {
+        for my $KeyTo ( sort keys %{ $Param{To} } ) {
             $NewTo{"$KeyTo||$Param{To}->{$KeyTo}"} = $Param{To}->{$KeyTo};
         }
@@ -1994,5 +2016,5 @@
     # prepare errors!
     if ( $Param{Errors} ) {
-        for my $KeyError ( keys %{ $Param{Errors} } ) {
+        for my $KeyError ( sort keys %{ $Param{Errors} } ) {
             $Param{$KeyError}
                 = '* ' . $Self->{LayoutObject}->Ascii2Html( Text => $Param{Errors}->{$KeyError} );
@@ -2341,4 +2363,9 @@
     # add rich text editor
     if ( $Self->{LayoutObject}->{BrowserRichText} ) {
+
+        # use height/width defined for this screen
+        $Param{RichTextHeight} = $Self->{Config}->{RichTextHeight} || 0;
+        $Param{RichTextWidth}  = $Self->{Config}->{RichTextWidth}  || 0;
+
         $Self->{LayoutObject}->Block(
             Name => 'RichText',

Author: ub

Index: AgentTicketEmail.pm
===================================================================
RCS file: /home/cvs/ITSMIncidentProblemManagement/Kernel/Modules/AgentTicketEmail.pm,v
retrieving revision 1.44
retrieving revision 1.45
diff -2 -u -d -r1.44 -r1.45
--- AgentTicketEmail.pm	22 Oct 2012 21:24:52 -0000	1.44
+++ AgentTicketEmail.pm	22 Nov 2012 13:50:27 -0000	1.45
@@ -4,5 +4,5 @@
 # --
 # $Id$
-# $OldId: AgentTicketEmail.pm,v 1.206.2.8 2012/10/17 20:20:40 cr Exp $
+# $OldId: AgentTicketEmail.pm,v 1.219 2012/11/20 14:48:37 mh Exp $
 # --
 # This software comes with ABSOLUTELY NO WARRANTY. For details, see
@@ -370,5 +370,5 @@
     my %DynamicFieldACLParameters;
     DYNAMICFIELD:
-    for my $DynamicField ( keys %DynamicFieldValues ) {
+    for my $DynamicField ( sort keys %DynamicFieldValues ) {
         next DYNAMICFIELD if !$DynamicField;
         next DYNAMICFIELD if !$DynamicFieldValues{$DynamicField};
@@ -522,4 +522,8 @@
                 if ( IsHashRefWithData( $DynamicFieldConfig->{Config}->{PossibleValues} ) ) {
 
+                    # convert possible values key => value to key => key for ACLs usign a Hash slice
+                    my %AclData = %{ $DynamicFieldConfig->{Config}->{PossibleValues} };
+                    @AclData{ keys %AclData } = keys %AclData;
+
                     # set possible values filter from ACLs
                     my $ACL = $Self->{TicketObject}->TicketAcl(
@@ -529,10 +533,14 @@
                         ReturnType    => 'Ticket',
                         ReturnSubType => 'DynamicField_' . $DynamicFieldConfig->{Name},
-                        Data          => $DynamicFieldConfig->{Config}->{PossibleValues},
+                        Data          => \%AclData,
                         UserID        => $Self->{UserID},
                     );
                     if ($ACL) {
                         my %Filter = $Self->{TicketObject}->TicketAclData();
-                        $PossibleValuesFilter = \%Filter;
+
+                        # convert Filer key => key back to key => value using map
+                        %{$PossibleValuesFilter}
+                            = map { $_ => $DynamicFieldConfig->{Config}->{PossibleValues}->{$_} }
+                            keys %Filter;
                     }
                 }
@@ -802,4 +810,8 @@
             if ( IsHashRefWithData( $DynamicFieldConfig->{Config}->{PossibleValues} ) ) {
 
+                # convert possible values key => value to key => key for ACLs usign a Hash slice
+                my %AclData = %{ $DynamicFieldConfig->{Config}->{PossibleValues} };
+                @AclData{ keys %AclData } = keys %AclData;
+
                 # set possible values filter from ACLs
                 my $ACL = $Self->{TicketObject}->TicketAcl(
@@ -809,10 +821,14 @@
                     ReturnType    => 'Ticket',
                     ReturnSubType => 'DynamicField_' . $DynamicFieldConfig->{Name},
-                    Data          => $DynamicFieldConfig->{Config}->{PossibleValues},
+                    Data          => \%AclData,
                     UserID        => $Self->{UserID},
                 );
                 if ($ACL) {
                     my %Filter = $Self->{TicketObject}->TicketAclData();
-                    $PossibleValuesFilter = \%Filter;
+
+                    # convert Filer key => key back to key => value using map
+                    %{$PossibleValuesFilter}
+                        = map { $_ => $DynamicFieldConfig->{Config}->{PossibleValues}->{$_} }
+                        keys %Filter;
                 }
             }
@@ -879,5 +895,5 @@
             # if just one, fillup CustomerUserID and CustomerID
             $Param{CustomerUserListCount} = 0;
-            for my $CustomerUserKey ( keys %CustomerUserList ) {
+            for my $CustomerUserKey ( sort keys %CustomerUserList ) {
                 $Param{CustomerUserListCount}++;
                 $Param{CustomerUserListLast}     = $CustomerUserList{$CustomerUserKey};
@@ -922,5 +938,5 @@
                 UserLogin => $CustomerUser,
             );
-            for my $CustomerUserKey ( keys %CustomerUserList ) {
+            for my $CustomerUserKey ( sort keys %CustomerUserList ) {
                 $GetParam{To} = $CustomerUserList{$CustomerUserKey};
             }
@@ -1493,5 +1509,5 @@
 
         if ($Tos) {
-            for my $KeyTo ( keys %{$Tos} ) {
+            for my $KeyTo ( sort keys %{$Tos} ) {
                 $NewTos->{"$KeyTo||$Tos->{$KeyTo}"} = $Tos->{$KeyTo};
             }
@@ -1556,4 +1572,8 @@
             );
 
+            # convert possible values key => value to key => key for ACLs usign a Hash slice
+            my %AclData = %{$PossibleValues};
+            @AclData{ keys %AclData } = keys %AclData;
+
             # set possible values filter from ACLs
             my $ACL = $Self->{TicketObject}->TicketAcl(
@@ -1565,10 +1585,12 @@
                 ReturnType    => 'Ticket',
                 ReturnSubType => 'DynamicField_' . $DynamicFieldConfig->{Name},
-                Data          => $PossibleValues,
+                Data          => \%AclData,
                 UserID        => $Self->{UserID},
             );
             if ($ACL) {
                 my %Filter = $Self->{TicketObject}->TicketAclData();
-                $PossibleValues = \%Filter;
+
+                # convert Filer key => key back to key => value using map
+                %{$PossibleValues} = map { $_ => $PossibleValues->{$_} } keys %Filter;
             }
 
@@ -1739,5 +1761,5 @@
     if ( $Param{QueueID} && !$Param{AllUsers} ) {
         my @UserIDs = $Self->{TicketObject}->GetSubscribedUserIDsByQueueID(%Param);
-        for my $GroupMemberKey ( keys %AllGroupsMembers ) {
+        for my $GroupMemberKey ( sort keys %AllGroupsMembers ) {
             my $Hit = 0;
             for my $UID (@UserIDs) {
@@ -1765,5 +1787,5 @@
             Result  => 'HASH',
         );
-        for my $MemberKey ( keys %MemberList ) {
+        for my $MemberKey ( sort keys %MemberList ) {
             if ( $AllGroupsMembers{$MemberKey} ) {
                 $ShownUsers{$MemberKey} = $AllGroupsMembers{$MemberKey};
@@ -1799,5 +1821,5 @@
     if ( $Param{QueueID} && !$Param{AllUsers} ) {
         my @UserIDs = $Self->{TicketObject}->GetSubscribedUserIDsByQueueID(%Param);
-        for my $GroupMemberKey ( keys %AllGroupsMembers ) {
+        for my $GroupMemberKey ( sort keys %AllGroupsMembers ) {
             my $Hit = 0;
             for my $UID (@UserIDs) {
@@ -1825,5 +1847,5 @@
             Result  => 'HASH',
         );
-        for my $MemberKey ( keys %MemberList ) {
+        for my $MemberKey ( sort keys %MemberList ) {
             if ( $AllGroupsMembers{$MemberKey} ) {
                 $ShownUsers{$MemberKey} = $AllGroupsMembers{$MemberKey};
@@ -1954,5 +1976,5 @@
 
         # build selection string
-        for my $QueueID ( keys %Tos ) {
+        for my $QueueID ( sort keys %Tos ) {
             my %QueueData = $Self->{QueueObject}->QueueGet( ID => $QueueID );
 
@@ -2038,5 +2060,5 @@
     my %NewTo;
     if ( $Param{FromList} ) {
-        for my $FromKey ( keys %{ $Param{FromList} } ) {
+        for my $FromKey ( sort keys %{ $Param{FromList} } ) {
             $NewTo{"$FromKey||$Param{FromList}->{$FromKey}"} = $Param{FromList}->{$FromKey};
         }
@@ -2077,5 +2099,5 @@
     # prepare errors!
     if ( $Param{Errors} ) {
-        for my $ErrorKey ( keys %{ $Param{Errors} } ) {
+        for my $ErrorKey ( sort keys %{ $Param{Errors} } ) {
             $Param{$ErrorKey}
                 = $Self->{LayoutObject}->Ascii2Html( Text => $Param{Errors}->{$ErrorKey} );
@@ -2553,4 +2575,9 @@
     # add rich text editor
     if ( $Self->{LayoutObject}->{BrowserRichText} ) {
+
+        # use height/width defined for this screen
+        $Param{RichTextHeight} = $Self->{Config}->{RichTextHeight} || 0;
+        $Param{RichTextWidth}  = $Self->{Config}->{RichTextWidth}  || 0;
+
         $Self->{LayoutObject}->Block(
             Name => 'RichText',

Author: ub

Index: CustomerTicketPrint.pm
===================================================================
RCS file: /home/cvs/ITSMIncidentProblemManagement/Kernel/Modules/CustomerTicketPrint.pm,v
retrieving revision 1.10
retrieving revision 1.11
diff -2 -u -d -r1.10 -r1.11
--- CustomerTicketPrint.pm	23 Jun 2012 12:09:49 -0000	1.10
+++ CustomerTicketPrint.pm	22 Nov 2012 13:50:27 -0000	1.11
@@ -4,5 +4,5 @@
 # --
 # $Id$
-# $OldId: CustomerTicketPrint.pm,v 1.48 2011/12/12 10:52:00 mg Exp $
+# $OldId: CustomerTicketPrint.pm,v 1.52 2012/11/20 14:54:03 mh Exp $
 # --
 # This software comes with ABSOLUTELY NO WARRANTY. For details, see
@@ -731,5 +731,5 @@
         }
         my $Attachments;
-        for my $FileID ( keys %AtmIndex ) {
+        for my $FileID ( sort keys %AtmIndex ) {
             my %File = %{ $AtmIndex{$FileID} };
             $Attachments .= $File{Filename} . ' (' . $File{Filesize} . ")\n";
@@ -1054,12 +1054,11 @@
         }
         $Param{'Article::ATM'} = '';
-        for my $FileID ( keys %AtmIndex ) {
+        for my $FileID ( sort keys %AtmIndex ) {
             my %File = %{ $AtmIndex{$FileID} };
             $File{Filename} = $Self->{LayoutObject}->Ascii2Html( Text => $File{Filename} );
             $Param{'Article::ATM'}
-                .= '<a href="$Env{"CGIHandle"}/$QData{"Filename"}?Action=CustomerTicketAttachment&'
+                .= '<a href="$Env{"Baselink"}Action=CustomerTicketAttachment;'
                 . "ArticleID=$Article{ArticleID};FileID=$FileID\" target=\"attachment\" "
-                . "onmouseover=\"window.status='\$Text{\"Download\"}: $File{Filename}';"
-                . ' return true;" onmouseout="window.status=\'\';">'
+                . "title=\"\$Text{\"Download\"}: $File{Filename}\">"
                 . "$File{Filename}</a> $File{Filesize}<br/>";
         }

Author: ub

Index: AgentTicketZoom.pm
===================================================================
RCS file: /home/cvs/ITSMIncidentProblemManagement/Kernel/Modules/AgentTicketZoom.pm,v
retrieving revision 1.36
retrieving revision 1.37
diff -2 -u -d -r1.36 -r1.37
--- AgentTicketZoom.pm	1 Aug 2012 12:11:59 -0000	1.36
+++ AgentTicketZoom.pm	22 Nov 2012 13:50:27 -0000	1.37
@@ -4,5 +4,5 @@
 # --
 # $Id$
-# $OldId: AgentTicketZoom.pm,v 1.177.2.1 2012/06/26 07:48:26 mg Exp $
+# $OldId: AgentTicketZoom.pm,v 1.194 2012/11/20 14:52:48 mh Exp $
 # --
 # This software comes with ABSOLUTELY NO WARRANTY. For details, see
@@ -17,10 +17,14 @@
 
 use Kernel::System::CustomerUser;
-use Kernel::System::LinkObject;
-use Kernel::System::EmailParser;
-use Kernel::System::SystemAddress;
 use Kernel::System::DynamicField;
 use Kernel::System::DynamicField::Backend;
-use Kernel::System::VariableCheck qw(:all);
+use Kernel::System::EmailParser;
+use Kernel::System::LinkObject;
+use Kernel::System::ProcessManagement::Activity;
+use Kernel::System::ProcessManagement::ActivityDialog;
+use Kernel::System::ProcessManagement::Process;
+use Kernel::System::ProcessManagement::Transition;
+use Kernel::System::ProcessManagement::TransitionAction;
+use Kernel::System::SystemAddress;
 # ---
 # ITSM
@@ -29,4 +33,6 @@
 # ---
 
+use Kernel::System::VariableCheck qw(:all);
+
 use vars qw($VERSION);
 $VERSION = qw($Revision$) [1];
@@ -93,11 +99,31 @@
 
     # get dynamic field config for frontend module
-    $Self->{DynamicFieldFilter}
-        = $Self->{ConfigObject}->Get("Ticket::Frontend::AgentTicketZoom")->{DynamicField};
-# ---
-# ITSM
-# ---
-    $Self->{GeneralCatalogObject} = Kernel::System::GeneralCatalog->new(%Param);
-# ---
+    $Self->{DynamicFieldFilter} = {
+        %{ $Self->{ConfigObject}->Get("Ticket::Frontend::AgentTicketZoom")->{DynamicField} || {} },
+        %{
+            $Self->{ConfigObject}->Get("Ticket::Frontend::AgentTicketZoom")
+                ->{ProcessWidgetDynamicField}
+                || {}
+        },
+    };
+
+    # create additional objects for process management
+    $Self->{ActivityObject} = Kernel::System::ProcessManagement::Activity->new(%Param);
+    $Self->{ActivityDialogObject}
+        = Kernel::System::ProcessManagement::ActivityDialog->new(%Param);
+
+    $Self->{TransitionObject} = Kernel::System::ProcessManagement::Transition->new(%Param);
+    $Self->{TransitionActionObject}
+        = Kernel::System::ProcessManagement::TransitionAction->new(%Param);
+
+    $Self->{ProcessObject} = Kernel::System::ProcessManagement::Process->new(
+        %Param,
+        ActivityObject         => $Self->{ActivityObject},
+        TransitionObject       => $Self->{TransitionObject},
+        TransitionActionObject => $Self->{TransitionActionObject},
+    );
+
+    # get zoom settings depending on ticket type
+    $Self->{DisplaySettings} = $Self->{ConfigObject}->Get("Ticket::Frontend::AgentTicketZoom");
 
     return $Self;
@@ -155,5 +181,10 @@
     # mark shown ticket as seen
     if ( $Self->{Subaction} eq 'TicketMarkAsSeen' ) {
-        my $Success = $Self->_TicketItemSeen( TicketID => $Self->{TicketID} );
+        my $Success = 1;
+
+        # always show archived tickets as seen
+        if ( $Ticket{ArchiveFlag} ne 'y' ) {
+            $Success = $Self->_TicketItemSeen( TicketID => $Self->{TicketID} );
+        }
 
         return $Self->{LayoutObject}->Attachment(
@@ -167,5 +198,10 @@
     # mark shown article as seen
     if ( $Self->{Subaction} eq 'MarkAsSeen' ) {
-        my $Success = $Self->_ArticleItemSeen( ArticleID => $Self->{ArticleID} );
+        my $Success = 1;
+
+        # always show archived tickets as seen
+        if ( $Ticket{ArchiveFlag} ne 'y' ) {
+            $Success = $Self->_ArticleItemSeen( ArticleID => $Self->{ArticleID} );
+        }
 
         return $Self->{LayoutObject}->Attachment(
@@ -444,4 +480,9 @@
     }
 
+    my %ArticleFlags = $Self->{TicketObject}->ArticleFlagsOfTicketGet(
+        TicketID => $Ticket{TicketID},
+        UserID   => $Self->{UserID},
+    );
+
     # get selected or last customer article
     my $ArticleID;
@@ -458,12 +499,7 @@
             next ARTICLE
                 if $Self->{ConfigObject}->Get('Ticket::NewArticleIgnoreSystemSender')
-                    && $Article->{SenderType} eq 'system';
+                && $Article->{SenderType} eq 'system';
 
-            # get article flags
-            my %ArticleFlag = $Self->{TicketObject}->ArticleFlagGet(
-                ArticleID => $Article->{ArticleID},
-                UserID    => $Self->{UserID},
-            );
-            next ARTICLE if $ArticleFlag{Seen};
+            next ARTICLE if $ArticleFlags{ $Article->{ArticleID} }->{Seen};
             $ArticleID = $Article->{ArticleID};
             last ARTICLE;
@@ -574,12 +610,32 @@
     }
 
-    # show article tree
-    $Param{ArticleTree} = $Self->_ArticleTree(
-        Ticket          => \%Ticket,
-        ArticleID       => $ArticleID,
-        ArticleMaxLimit => $ArticleMaxLimit,
-        ArticleBox      => \@ArticleBox,
+    # set display options
+    $Param{WidgetTitle} = 'Ticket Information';
+    $Param{Hook} = $Self->{ConfigObject}->Get('Ticket::Hook') || 'Ticket#';
+
+    # check if ticket is normal or process ticket
+    my $IsProcessTicket = $Self->{TicketObject}->TicketCheckForProcessType(
+        'TicketID' => $Self->{TicketID}
     );
 
+    # overwrite display options for process ticket
+    if ($IsProcessTicket) {
+        $Param{WidgetTitle} = $Self->{DisplaySettings}->{ProcessDisplay}->{WidgetTitle};
+        $Param{Hook} = $Self->{DisplaySettings}->{ProcessDisplay}->{Hook} || 'Process#';
+    }
+
+    # only show article tree if articles are present
+    if (@ArticleBox) {
+
+        # show article tree
+        $Param{ArticleTree} = $Self->_ArticleTree(
+            Ticket          => \%Ticket,
+            ArticleFlags    => \%ArticleFlags,
+            ArticleID       => $ArticleID,
+            ArticleMaxLimit => $ArticleMaxLimit,
+            ArticleBox      => \@ArticleBox,
+        );
+    }
+
     # show articles items
     $Param{ArticleItems} = '';
@@ -609,5 +665,6 @@
     }
 
-    if ( $Self->{ZoomExpand} ) {
+    # always show archived tickets as seen
+    if ( $Self->{ZoomExpand} && $Ticket{ArchiveFlag} ne 'y' ) {
         $Self->{LayoutObject}->Block(
             Name => 'TicketItemMarkAsSeen',
@@ -709,4 +766,11 @@
     }
 
+    if ( $Ticket{ArchiveFlag} eq 'y' ) {
+        $Self->{LayoutObject}->Block(
+            Name => 'ArchiveFlag',
+            Data => { %Ticket, %AclAction },
+        );
+    }
+
     # ticket type
     if ( $Self->{ConfigObject}->Get('Ticket::Type') ) {
@@ -869,4 +933,163 @@
     }
 
+    # show no articles block if ticket does not contain articles
+    if ( !@ArticleBox ) {
+        $Self->{LayoutObject}->Block(
+            Name => 'HintNoArticles',
+        );
+    }
+
+    # show process widget  and activity dialogs on process tickets
+    if ($IsProcessTicket) {
+
+        # get the DF where the ProcessEntityID is stored
+        my $ProcessEntityIDField = 'DynamicField_'
+            . $Self->{ConfigObject}->Get("Process::DynamicFieldProcessManagementProcessID");
+
+        # get the DF where the AtivityEntityID is stored
+        my $ActivityEntityIDField = 'DynamicField_'
+            . $Self->{ConfigObject}->Get("Process::DynamicFieldProcessManagementActivityID");
+
+        my $ProcessData = $Self->{ProcessObject}->ProcessGet(
+            ProcessEntityID => $Ticket{$ProcessEntityIDField},
+        );
+        my $ActivityData = $Self->{ActivityObject}->ActivityGet(
+            Interface        => 'AgentInterface',
+            ActivityEntityID => $Ticket{$ActivityEntityIDField},
+        );
+
+        # output process information in the sidebar
+        $Self->{LayoutObject}->Block(
+            Name => 'ProcessData',
+            Data => {
+                Process  => $ProcessData->{Name}  || '',
+                Activity => $ActivityData->{Name} || '',
+            },
+        );
+
+        # output the process widget the the main screen
+        $Self->{LayoutObject}->Block(
+            Name => 'ProcessWidget',
+            Data => {
+                WidgetTitle => $Param{WidgetTitle},
+            },
+        );
+
+        # get next activity dialogs
+        my $NextActivityDialogs;
+        if ( $Ticket{$ActivityEntityIDField} ) {
+            $NextActivityDialogs = $ActivityData;
+        }
+
+        if ( IsHashRefWithData($NextActivityDialogs) ) {
+
+            # we don't need the whole Activity config,
+            # just the Activity Dialogs of the current Activity
+            if ( IsHashRefWithData( $NextActivityDialogs->{ActivityDialog} ) ) {
+                %{$NextActivityDialogs} = %{ $NextActivityDialogs->{ActivityDialog} };
+            }
+            else {
+                $NextActivityDialogs = {};
+            }
+
+            # ACL Check is done in the initial "Run" statement
+            # so here we can just pick the possibly reduced Activity Dialogs
+            # map and sort reformat the $NextActivityDialogs hash from it's initial form e.g.:
+            # 1 => 'AD1',
+            # 2 => 'AD3',
+            # 3 => 'AD2',
+            # to a regular array in correct order:
+            # ('AD1', 'AD3', 'AD2')
+
+            my @TmpActivityDialogList
+                = map { $NextActivityDialogs->{$_} } sort keys %{$NextActivityDialogs};
+
+            # we have to check if the current user has the needed permissions to view the
+            # different activity dialogs, so we loop over every activity dialog and check if there
+            # is a permission configured. If there is a permission configured we check this
+            # and display/hide the activity dialog link
+            my %PermissionRights;
+            my @PermissionActivityDialogList;
+            ACTIVITYDIALOGPERMISSION:
+            for my $CurrentActivityDialogEntityID (@TmpActivityDialogList) {
+                my $CurrentActivityDialog
+                    = $Self->{ActivityDialogObject}->ActivityDialogGet(
+                    Interface              => 'AgentInterface',
+                    ActivityDialogEntityID => $CurrentActivityDialogEntityID
+                    );
+
+                # create an interface lookuplist
+                my %InterfaceLookup = map { $_ => 1 } @{ $CurrentActivityDialog->{Interface} };
+
+                next ACTIVITYDIALOGPERMISSION if !$InterfaceLookup{AgentInterface};
+
+                if ( $CurrentActivityDialog->{Permission} ) {
+
+                    # performanceboost/cache
+                    if ( !defined $PermissionRights{ $CurrentActivityDialog->{Permission} } ) {
+                        $PermissionRights{ $CurrentActivityDialog->{Permission} }
+                            = $Self->{TicketObject}->TicketPermission(
+                            Type     => $CurrentActivityDialog->{Permission},
+                            TicketID => $Ticket{TicketID},
+                            UserID   => $Self->{UserID},
+                            );
+                    }
+
+                    next ACTIVITYDIALOGPERMISSION
+                        if !$PermissionRights{ $CurrentActivityDialog->{Permission} };
+                }
+
+                push @PermissionActivityDialogList, $CurrentActivityDialogEntityID;
+            }
+
+            my @PossibleActivityDialogs;
+            if (@PermissionActivityDialogList) {
+                @PossibleActivityDialogs
+                    = $Self->{TicketObject}->TicketAclActivityDialogData(
+                    ActivityDialogs => \@PermissionActivityDialogList
+                    );
+            }
+
+            # reformat the @PossibleActivityDialogs that is of the structure:
+            # @PossibleActivityDialogs = ('AD1', 'AD3', 'AD4', 'AD2');
+            # to get the same structure as in the %NextActivityDialogs
+            # e.g.:
+            # 1 => 'AD1',
+            # 2 => 'AD3',
+            %{$NextActivityDialogs}
+                = map { $_ => $PossibleActivityDialogs[ $_ - 1 ] }
+                1 .. scalar @PossibleActivityDialogs;
+
+            $Self->{LayoutObject}->Block(
+                Name => 'NextActivityDialogs',
+            );
+
+            if ( IsHashRefWithData($NextActivityDialogs) ) {
+                for my $NextActivityDialogKey ( sort keys %{$NextActivityDialogs} ) {
+                    my $ActivityDialogData = $Self->{ActivityDialogObject}->ActivityDialogGet(
+                        Interface              => 'AgentInterface',
+                        ActivityDialogEntityID => $NextActivityDialogs->{$NextActivityDialogKey},
+                    );
+                    $Self->{LayoutObject}->Block(
+                        Name => 'ActivityDialog',
+                        Data => {
+                            ActivityDialogEntityID
+                                => $NextActivityDialogs->{$NextActivityDialogKey},
+                            Name            => $ActivityDialogData->{Name},
+                            ProcessEntityID => $Ticket{$ProcessEntityIDField},
+                            TicketID        => $Ticket{TicketID},
+                        },
+                    );
+                }
+            }
+            else {
+                $Self->{LayoutObject}->Block(
+                    Name => 'NoActivityDialogs',
+                    Data => {},
+                );
+            }
+        }
+    }
+
     # get the dynamic fields for ticket object
     my $DynamicField = $Self->{DynamicFieldObject}->DynamicFieldListGet(
@@ -881,4 +1104,7 @@
 # ---
 
+    # to store dynamic fields to be displayed in the process widget and in the sidebar
+    my ( @FieldsWidget, @FieldsSidebar );
+
     # cycle trough the activated Dynamic Fields for ticket object
     DYNAMICFIELD:
@@ -898,39 +1124,50 @@
 
         # get print string for this dynamic field
+        # do not use ValueMaxChars here otherwise values will be trimmed also in Process Widget
         my $ValueStrg = $Self->{BackendObject}->DisplayValueRender(
             DynamicFieldConfig => $DynamicFieldConfig,
             Value              => $Ticket{ 'DynamicField_' . $DynamicFieldConfig->{Name} },
-            ValueMaxChars      => 25,
             LayoutObject       => $Self->{LayoutObject},
         );
 
-        my $Label = $DynamicFieldConfig->{Label};
-
-        $Self->{LayoutObject}->Block(
-            Name => 'TicketDynamicField',
-            Data => {
-                Label => $Label,
-            },
-        );
+        # use translation here to be able to reduce the character length in the template
+        my $Label = $Self->{LayoutObject}->{LanguageObject}->Get( $DynamicFieldConfig->{Label} );
 
-        if ( $ValueStrg->{Link} ) {
-            $Self->{LayoutObject}->Block(
-                Name => 'TicketDynamicFieldLink',
-                Data => {
-                    Value                       => $ValueStrg->{Value},
-                    Title                       => $ValueStrg->{Title},
-                    Link                        => $ValueStrg->{Link},
-                    $DynamicFieldConfig->{Name} => $ValueStrg->{Title},
-                },
-            );
+        if (
+            $IsProcessTicket &&
+            $Self->{DisplaySettings}->{ProcessWidgetDynamicField}->{ $DynamicFieldConfig->{Name} }
+            )
+        {
+            push @FieldsWidget, {
+                Name  => $DynamicFieldConfig->{Name},
+                Title => $ValueStrg->{Title},
+                Value => $ValueStrg->{Value},
+                ValueKey
+                    => $Ticket{ 'DynamicField_' . $DynamicFieldConfig->{Name} },
+                Label                       => $Label,
+                Link                        => $ValueStrg->{Link},
+                $DynamicFieldConfig->{Name} => $ValueStrg->{Title},
+            };
         }
-        else {
-            $Self->{LayoutObject}->Block(
-                Name => 'TicketDynamicFieldPlain',
-                Data => {
-                    Value => $ValueStrg->{Value},
-                    Title => $ValueStrg->{Title},
-                },
-            );
+
+        if (
+            $Self->{DisplaySettings}->{DynamicField}->{ $DynamicFieldConfig->{Name} }
+            )
+        {
+            my $TrimmedValue = $ValueStrg->{Value};
+
+            # trim the value so it can fit better in the sidebar
+            if ( length $ValueStrg->{Value} > 18 ) {
+                $TrimmedValue = substr( $ValueStrg->{Value}, 0, 18 ) . '...';
+            }
+
+            push @FieldsSidebar, {
+                Name                        => $DynamicFieldConfig->{Name},
+                Title                       => $ValueStrg->{Title},
+                Value                       => $TrimmedValue,
+                Label                       => $Label,
+                Link                        => $ValueStrg->{Link},
+                $DynamicFieldConfig->{Name} => $ValueStrg->{Title},
+            };
         }
 
@@ -999,4 +1236,169 @@
 # ---
 
+    if ($IsProcessTicket) {
+
+        # output dynamic fields registered for a group in the process widget
+        my @FieldsInAGroup;
+        for my $GroupName (
+            sort keys %{ $Self->{DisplaySettings}->{ProcessWidgetDynamicFieldGroups} }
+            )
+        {
+
+            $Self->{LayoutObject}->Block(
+                Name => 'ProcessWidgetDynamicFieldGroups',
+            );
+
+            my $GroupFieldsString
+                = $Self->{DisplaySettings}->{ProcessWidgetDynamicFieldGroups}->{$GroupName};
+
+            $GroupFieldsString =~ s{\s}{}xmsg;
+            my @GroupFields = split( ',', $GroupFieldsString );
+
+            if ( $#GroupFields + 1 ) {
+
+                my $ShowGroupTitle = 0;
+                for my $Field (@FieldsWidget) {
+
+                    if ( grep { $_ eq $Field->{Name} } @GroupFields ) {
+
+                        $ShowGroupTitle = 1;
+                        $Self->{LayoutObject}->Block(
+                            Name => 'ProcessWidgetDynamicField',
+                            Data => {
+                                Label => $Field->{Label},
+                                Name  => $Field->{Name},
+                            },
+                        );
+
+                        $Self->{LayoutObject}->Block(
+                            Name => 'ProcessWidgetDynamicFieldValueOverlayTrigger',
+                        );
+
+                        if ( $Field->{Link} ) {
+                            $Self->{LayoutObject}->Block(
+                                Name => 'ProcessWidgetDynamicFieldLink',
+                                Data => {
+                                    Value          => $Field->{Value},
+                                    Title          => $Field->{Title},
+                                    Link           => $Field->{Link},
+                                    $Field->{Name} => $Field->{Title},
+                                },
+                            );
+                        }
+                        else {
+                            $Self->{LayoutObject}->Block(
+                                Name => 'ProcessWidgetDynamicFieldPlain',
+                                Data => {
+                                    Value => $Field->{Value},
+                                    Title => $Field->{Title},
+                                },
+                            );
+                        }
+                        push @FieldsInAGroup, $Field->{Name};
+                    }
+                }
+
+                if ($ShowGroupTitle) {
+                    $Self->{LayoutObject}->Block(
+                        Name => 'ProcessWidgetDynamicFieldGroupSeparator',
+                        Data => {
+                            Name => $GroupName,
+                        },
+                    );
+                }
+            }
+        }
+
+        # output dynamic fields not registered in a group in the process widget
+        my @RemainingFieldsWidget;
+        for my $Field (@FieldsWidget) {
+
+            if ( !grep { $_ eq $Field->{Name} } @FieldsInAGroup ) {
+                push @RemainingFieldsWidget, $Field;
+            }
+        }
+
+        $Self->{LayoutObject}->Block(
+            Name => 'ProcessWidgetDynamicFieldGroups',
+        );
+
+        if ( $#RemainingFieldsWidget + 1 ) {
+
+            $Self->{LayoutObject}->Block(
+                Name => 'ProcessWidgetDynamicFieldGroupSeparator',
+                Data => {
+                    Name => $Self->{LayoutObject}->{LanguageObject}->Get('Fields with no group'),
+                },
+            );
+        }
+        for my $Field (@RemainingFieldsWidget) {
+
+            $Self->{LayoutObject}->Block(
+                Name => 'ProcessWidgetDynamicField',
+                Data => {
+                    Label => $Field->{Label},
+                    Name  => $Field->{Name},
+                },
+            );
+
+            $Self->{LayoutObject}->Block(
+                Name => 'ProcessWidgetDynamicFieldValueOverlayTrigger',
+            );
+
+            if ( $Field->{Link} ) {
+                $Self->{LayoutObject}->Block(
+                    Name => 'ProcessWidgetDynamicFieldLink',
+                    Data => {
+                        Value          => $Field->{Value},
+                        Title          => $Field->{Title},
+                        Link           => $Field->{Link},
+                        $Field->{Name} => $Field->{Title},
+                    },
+                );
+            }
+            else {
+                $Self->{LayoutObject}->Block(
+                    Name => 'ProcessWidgetDynamicFieldPlain',
+                    Data => {
+                        Value => $Field->{Value},
+                        Title => $Field->{Title},
+                    },
+                );
+            }
+        }
+    }
+
+    # output dynamic fields in the sidebar
+    for my $Field (@FieldsSidebar) {
+
+        $Self->{LayoutObject}->Block(
+            Name => 'TicketDynamicField',
+            Data => {
+                Label => $Field->{Label},
+            },
+        );
+
+        if ( $Field->{Link} ) {
+            $Self->{LayoutObject}->Block(
+                Name => 'TicketDynamicFieldLink',
+                Data => {
+                    Value          => $Field->{Value},
+                    Title          => $Field->{Title},
+                    Link           => $Field->{Link},
+                    $Field->{Name} => $Field->{Title},
+                },
+            );
+        }
+        else {
+            $Self->{LayoutObject}->Block(
+                Name => 'TicketDynamicFieldPlain',
+                Data => {
+                    Value => $Field->{Value},
+                    Title => $Field->{Title},
+                },
+            );
+        }
+    }
+
     # customer info string
     if ( $Self->{ConfigObject}->Get('Ticket::Frontend::CustomerInfoZoom') ) {
@@ -1107,14 +1509,8 @@
         next ARTICLE
             if $Self->{ConfigObject}->Get('Ticket::NewArticleIgnoreSystemSender')
-                && $Article->{SenderType} eq 'system';
-
-        # get article flags
-        my %ArticleFlag = $Self->{TicketObject}->ArticleFlagGet(
-            ArticleID => $Article->{ArticleID},
-            UserID    => $Self->{UserID},
-        );
+            && $Article->{SenderType} eq 'system';
 
         # last if article was not shown
-        if ( !$ArticleFlag{Seen} ) {
+        if ( !$ArticleFlags{ $Article->{ArticleID} }->{Seen} ) {
             $ArticleAllSeen = 0;
             last ARTICLE;
@@ -1149,4 +1545,5 @@
 
     my %Ticket          = %{ $Param{Ticket} };
+    my %ArticleFlags    = %{ $Param{ArticleFlags} };
     my @ArticleBox      = @{ $Param{ArticleBox} };
     my $ArticleMaxLimit = $Param{ArticleMaxLimit};
@@ -1238,15 +1635,11 @@
 
         # show article flags
-        my $Class       = '';
-        my $ClassRow    = '';
-        my $NewArticle  = 0;
-        my %ArticleFlag = $Self->{TicketObject}->ArticleFlagGet(
-            ArticleID => $Article{ArticleID},
-            UserID    => $Self->{UserID},
-        );
+        my $Class      = '';
+        my $ClassRow   = '';
+        my $NewArticle = 0;
 
         # ignore system sender types
         if (
-            !$ArticleFlag{Seen}
+            !$ArticleFlags{ $Article{ArticleID} }->{Seen}
             && (
                 !$Self->{ConfigObject}->Get('Ticket::NewArticleIgnoreSystemSender')
@@ -1259,6 +1652,10 @@
 
             # show ticket flags
-            $Class    .= ' UnreadArticles';
-            $ClassRow .= ' UnreadArticles';
+
+            # always show archived tickets as seen
+            if ( $Ticket{ArchiveFlag} ne 'y' ) {
+                $Class    .= ' UnreadArticles';
+                $ClassRow .= ' UnreadArticles';
+            }
 
             # just show ticket flags if agent belongs to the ticket
@@ -1312,5 +1709,6 @@
         );
 
-        if ($NewArticle) {
+        # always show archived tickets as seen
+        if ( $NewArticle && $Ticket{ArchiveFlag} ne 'y' ) {
             $Self->{LayoutObject}->Block(
                 Name => 'TreeItemNewArticle',
@@ -1380,5 +1778,5 @@
                 );
 
-                if ( keys %{ $Article{Atms} } > 1 ) {
+                if ( scalar keys %{ $Article{Atms} } > 1 ) {
                     $Self->{LayoutObject}->Block(
                         Name => 'TreeItemAttachmentIconMultiple',
@@ -1481,19 +1879,23 @@
     }
 
-    # mark shown article as seen
-    if ( $Param{Type} eq 'OnLoad' ) {
-        $Self->_ArticleItemSeen( ArticleID => $Article{ArticleID} );
-    }
-    else {
-        if (
-            !$Self->{ZoomExpand}
-            && defined $Param{ActualArticleID}
-            && $Param{ActualArticleID} == $Article{ArticleID}
-            )
-        {
-            $Self->{LayoutObject}->Block(
-                Name => 'ArticleItemMarkAsSeen',
-                Data => { %Param, %Article, %AclAction },
-            );
+    # always show archived tickets as seen
+    if ( $Ticket{ArchiveFlag} ne 'y' ) {
+
+        # mark shown article as seen
+        if ( $Param{Type} eq 'OnLoad' ) {
+            $Self->_ArticleItemSeen( ArticleID => $Article{ArticleID} );
+        }
+        else {
+            if (
+                !$Self->{ZoomExpand}
+                && defined $Param{ActualArticleID}
+                && $Param{ActualArticleID} == $Article{ArticleID}
+                )
+            {
+                $Self->{LayoutObject}->Block(
+                    Name => 'ArticleItemMarkAsSeen',
+                    Data => { %Param, %Article, %AclAction },
+                );
+            }
         }
     }
---------------------------------------------------------------------
OTRS mailing list: cvs-log - Webpage: http://otrs.org/
Archive: http://lists.otrs.org/pipermail/cvs-log
To unsubscribe: http://lists.otrs.org/cgi-bin/listinfo/cvs-log
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.