# -- # Copyright (C) 2001-2019 OTRS AG, https://otrs.com/ # -- # This software comes with ABSOLUTELY NO WARRANTY. For details, see # the enclosed file COPYING for license information (GPL). If you # did not receive this file, see https://www.gnu.org/licenses/gpl-3.0.txt. # -- package Kernel::Output::HTML::Layout::Ticket; use strict; use warnings; use Kernel::System::VariableCheck qw(:all); use Kernel::Language qw(Translatable); our $ObjectManagerDisabled = 1; =head1 NAME Kernel::Output::HTML::Layout::Ticket - all Ticket-related HTML functions =head1 DESCRIPTION All Ticket-related HTML functions =head1 PUBLIC INTERFACE =head2 AgentCustomerViewTable() =cut sub AgentCustomerViewTable { my ( $Self, %Param ) = @_; # check customer params if ( ref $Param{Data} ne 'HASH' ) { $Self->FatalError( Message => 'Need Hash ref in Data param' ); } elsif ( ref $Param{Data} eq 'HASH' && !%{ $Param{Data} } ) { return $Self->{LanguageObject}->Translate('none'); } # add ticket params if given if ( $Param{Ticket} ) { %{ $Param{Data} } = ( %{ $Param{Data} }, %{ $Param{Ticket} } ); } my @MapNew; my $Map = $Param{Data}->{Config}->{Map}; if ($Map) { @MapNew = ( @{$Map} ); } # check if customer company support is enabled if ( $Param{Data}->{Config}->{CustomerCompanySupport} ) { my $Map2 = $Param{Data}->{CompanyConfig}->{Map}; if ($Map2) { push( @MapNew, @{$Map2} ); } } my $ShownType = 1; if ( $Param{Type} && $Param{Type} eq Translatable('Lite') ) { $ShownType = 2; # check if min one lite view item is configured, if not, use # the normal view also my $Used = 0; for my $Field (@MapNew) { if ( $Field->[3] == 2 ) { $Used = 1; } } if ( !$Used ) { $ShownType = 1; } } # build html table $Self->Block( Name => 'Customer', Data => $Param{Data}, ); # get needed objects my $ConfigObject = $Kernel::OM->Get('Kernel::Config'); my $MainObject = $Kernel::OM->Get('Kernel::System::Main'); # check Frontend::CustomerUser::Image my $CustomerImage = $ConfigObject->Get('Frontend::CustomerUser::Image'); if ($CustomerImage) { my %Modules = %{$CustomerImage}; MODULE: for my $Module ( sort keys %Modules ) { if ( !$MainObject->Require( $Modules{$Module}->{Module} ) ) { $Self->FatalDie(); } my $Object = $Modules{$Module}->{Module}->new( %{$Self}, LayoutObject => $Self, ); # run module next MODULE if !$Object; $Object->Run( Config => $Modules{$Module}, Data => $Param{Data}, ); } } my $DynamicFieldConfigs = $Kernel::OM->Get('Kernel::System::DynamicField')->DynamicFieldListGet( ObjectType => [ 'CustomerUser', 'CustomerCompany', ], ); my %DynamicFieldLookup = map { $_->{Name} => $_ } @{$DynamicFieldConfigs}; # Get dynamic field object. my $DynamicFieldBackendObject = $Kernel::OM->Get('Kernel::System::DynamicField::Backend'); # build table FIELD: for my $Field (@MapNew) { if ( $Field->[3] && $Field->[3] >= $ShownType && $Param{Data}->{ $Field->[0] } ) { my %Record = ( %{ $Param{Data} }, Key => $Field->[1], Value => $Param{Data}->{ $Field->[0] }, ); # render dynamic field values if ( $Field->[5] eq 'dynamic_field' ) { if ( !IsArrayRefWithData( $Record{Value} ) ) { $Record{Value} = [ $Record{Value} ]; } my $DynamicFieldConfig = $DynamicFieldLookup{ $Field->[2] }; next FIELD if !$DynamicFieldConfig; my @RenderedValues; VALUE: for my $Value ( @{ $Record{Value} } ) { my $RenderedValue = $DynamicFieldBackendObject->DisplayValueRender( DynamicFieldConfig => $DynamicFieldConfig, Value => $Value, HTMLOutput => 0, LayoutObject => $Self, ); next VALUE if !IsHashRefWithData($RenderedValue) || !defined $RenderedValue->{Value}; # If there is configured show link in DF, save as map value. $Field->[6] = $RenderedValue->{Link} ? $RenderedValue->{Link} : $Field->[6]; push @RenderedValues, $RenderedValue->{Value}; } $Record{Value} = join ', ', @RenderedValues; $Record{Key} = $DynamicFieldConfig->{Label}; } if ( $Field->[6] && ( $Param{Data}->{TicketID} || $Param{Ticket} || $Field->[6] !~ m{Env\("CGIHandle"\)} ) ) { $Record{LinkStart} = "[6]\""; if ( !$Param{Ticket} ) { $Record{LinkStart} .= " target=\"_blank\""; } elsif ( $Field->[8] ) { $Record{LinkStart} .= " target=\"$Field->[8]\""; } if ( $Field->[9] ) { $Record{LinkStart} .= " class=\"$Field->[9]\""; } $Record{LinkStart} .= ">"; $Record{LinkStop} = ""; } if ( $Field->[0] ) { $Record{ValueShort} = $Self->Ascii2Html( Text => $Record{Value}, Max => $Param{Max} ); } $Self->Block( Name => 'CustomerRow', Data => \%Record, ); if ( $Param{Data}->{Config}->{CustomerCompanySupport} && $Field->[0] eq 'CustomerCompanyName' ) { my $CompanyValidID = $Param{Data}->{CustomerCompanyValidID}; if ($CompanyValidID) { my @ValidIDs = $Kernel::OM->Get('Kernel::System::Valid')->ValidIDsGet(); my $CompanyIsValid = grep { $CompanyValidID == $_ } @ValidIDs; if ( !$CompanyIsValid ) { $Self->Block( Name => 'CustomerRowCustomerCompanyInvalid', ); } } } if ( $ConfigObject->Get('ChatEngine::Active') && $Field->[0] eq 'UserLogin' ) { # Check if agent has permission to start chats with the customer users. my $EnableChat = 1; my $ChatStartingAgentsGroup = $ConfigObject->Get('ChatEngine::PermissionGroup::ChatStartingAgents') || 'users'; my $ChatStartingAgentsGroupPermission = $Kernel::OM->Get('Kernel::System::Group')->PermissionCheck( UserID => $Self->{UserID}, GroupName => $ChatStartingAgentsGroup, Type => 'rw', ); if ( !$ChatStartingAgentsGroupPermission ) { $EnableChat = 0; } if ( $EnableChat && !$ConfigObject->Get('ChatEngine::ChatDirection::AgentToCustomer') ) { $EnableChat = 0; } if ($EnableChat) { my $VideoChatEnabled = 0; my $VideoChatAgentsGroup = $ConfigObject->Get('ChatEngine::PermissionGroup::VideoChatAgents') || 'users'; my $VideoChatAgentsGroupPermission = $Kernel::OM->Get('Kernel::System::Group')->PermissionCheck( UserID => $Self->{UserID}, GroupName => $VideoChatAgentsGroup, Type => 'rw', ); # Enable the video chat feature if system is entitled and agent is a member of configured group. if ($VideoChatAgentsGroupPermission) { if ( $Kernel::OM->Get('Kernel::System::Main') ->Require( 'Kernel::System::VideoChat', Silent => 1 ) ) { $VideoChatEnabled = $Kernel::OM->Get('Kernel::System::VideoChat')->IsEnabled(); } } my $CustomerEnableChat = 0; my $ChatAccess = 0; my $VideoChatAvailable = 0; my $VideoChatSupport = 0; # Default status is offline. my $UserState = Translatable('Offline'); my $UserStateDescription = $Self->{LanguageObject}->Translate('User is currently offline.'); my $CustomerChatAvailability = $Kernel::OM->Get('Kernel::System::Chat')->CustomerAvailabilityGet( UserID => $Param{Data}->{UserID}, ); my $CustomerUserObject = $Kernel::OM->Get('Kernel::System::CustomerUser'); my %CustomerUser = $CustomerUserObject->CustomerUserDataGet( User => $Param{Data}->{UserID}, ); $CustomerUser{UserFullname} = $CustomerUserObject->CustomerName( UserLogin => $Param{Data}->{UserID}, ); $VideoChatSupport = 1 if $CustomerUser{VideoChatHasWebRTC}; if ( $CustomerChatAvailability == 3 ) { $UserState = Translatable('Active'); $CustomerEnableChat = 1; $UserStateDescription = $Self->{LanguageObject}->Translate('User is currently active.'); $VideoChatAvailable = 1; } elsif ( $CustomerChatAvailability == 2 ) { $UserState = Translatable('Away'); $CustomerEnableChat = 1; $UserStateDescription = $Self->{LanguageObject}->Translate('User was inactive for a while.'); } $Self->Block( Name => 'CustomerRowUserStatus', Data => { %CustomerUser, UserState => $UserState, UserStateDescription => $UserStateDescription, }, ); if ($CustomerEnableChat) { $Self->Block( Name => 'CustomerRowChatIcons', Data => { %{ $Param{Data} }, %CustomerUser, VideoChatEnabled => $VideoChatEnabled, VideoChatAvailable => $VideoChatAvailable, VideoChatSupport => $VideoChatSupport, }, ); } } } } } # check Frontend::CustomerUser::Item my $CustomerItem = $ConfigObject->Get('Frontend::CustomerUser::Item'); my $CustomerItemCount = 0; if ($CustomerItem) { $Self->Block( Name => 'CustomerItem', ); my %Modules = %{$CustomerItem}; MODULE: for my $Module ( sort keys %Modules ) { if ( !$MainObject->Require( $Modules{$Module}->{Module} ) ) { $Self->FatalDie(); } my $Object = $Modules{$Module}->{Module}->new( %{$Self}, LayoutObject => $Self, ); # run module next MODULE if !$Object; my $Run = $Object->Run( Config => $Modules{$Module}, Data => $Param{Data}, ); next MODULE if !$Run; $CustomerItemCount++; } } # create & return output return $Self->Output( TemplateFile => 'AgentCustomerTableView', Data => \%Param ); } sub AgentQueueListOption { my ( $Self, %Param ) = @_; my $Size = $Param{Size} ? "size='$Param{Size}'" : ''; my $MaxLevel = defined( $Param{MaxLevel} ) ? $Param{MaxLevel} : 10; my $SelectedID = defined( $Param{SelectedID} ) ? $Param{SelectedID} : ''; my $Selected = defined( $Param{Selected} ) ? $Param{Selected} : ''; my $CurrentQueueID = defined( $Param{CurrentQueueID} ) ? $Param{CurrentQueueID} : ''; my $Class = defined( $Param{Class} ) ? $Param{Class} : ''; my $SelectedIDRefArray = $Param{SelectedIDRefArray} || ''; my $Multiple = $Param{Multiple} ? 'multiple = "multiple"' : ''; my $TreeView = $Param{TreeView} ? $Param{TreeView} : 0; my $OptionTitle = defined( $Param{OptionTitle} ) ? $Param{OptionTitle} : 0; my $OnChangeSubmit = defined( $Param{OnChangeSubmit} ) ? $Param{OnChangeSubmit} : ''; if ($OnChangeSubmit) { $OnChangeSubmit = " onchange=\"submit();\""; } else { $OnChangeSubmit = ''; } # set OnChange if AJAX is used if ( $Param{Ajax} ) { # get log object my $LogObject = $Kernel::OM->Get('Kernel::System::Log'); if ( !$Param{Ajax}->{Depend} ) { $LogObject->Log( Priority => 'error', Message => 'Need Depend Param Ajax option!', ); $Self->FatalError(); } if ( !$Param{Ajax}->{Update} ) { $LogObject->Log( Priority => 'error', Message => 'Need Update Param Ajax option()!', ); $Self->FatalError(); } $Param{OnChange} = "Core.AJAX.FormUpdate(\$('#" . $Param{Name} . "'), '" . $Param{Ajax}->{Subaction} . "'," . " '$Param{Name}'," . " ['" . join( "', '", @{ $Param{Ajax}->{Update} } ) . "']);"; } if ( $Param{OnChange} ) { $OnChangeSubmit = " onchange=\"$Param{OnChange}\""; } # just show a simple list if ( $Kernel::OM->Get('Kernel::Config')->Get('Ticket::Frontend::ListType') eq 'list' ) { # transform data from Hash in Array because of ordering in frontend by Queue name # it was a problem with name like '(some_queue)' # see bug#10621 http://bugs.otrs.org/show_bug.cgi?id=10621 my %QueueDataHash = %{ $Param{Data} || {} }; my @QueueDataArray = map { { Key => $_, Value => $QueueDataHash{$_}, } } sort { $QueueDataHash{$a} cmp $QueueDataHash{$b} } keys %QueueDataHash; # find index of first element in array @QueueDataArray for displaying in frontend # at the top should be element with ' $QueueDataArray[$_]->{Key} = 0' like "- Move -" # if such an element is found, it is moved to the top my $MoveStr = $Self->{LanguageObject}->Translate('Move'); my $ValueOfQueueNoKey = '- ' . $MoveStr . ' -'; my ($FirstElementIndex) = grep { $QueueDataArray[$_]->{Value} eq '-' || $QueueDataArray[$_]->{Value} eq $ValueOfQueueNoKey } 0 .. scalar(@QueueDataArray) - 1; if ($FirstElementIndex) { splice( @QueueDataArray, 0, 0, splice( @QueueDataArray, $FirstElementIndex, 1 ) ); } $Param{Data} = \@QueueDataArray; $Param{MoveQueuesStrg} = $Self->BuildSelection( %Param, HTMLQuote => 0, SelectedID => $Param{SelectedID} || $Param{SelectedIDRefArray} || '', SelectedValue => $Param{Selected}, Translation => 0, ); return $Param{MoveQueuesStrg}; } # build tree list $Param{MoveQueuesStrg} = '\n"; if ( $Param{TreeView} ) { my $TreeSelectionMessage = $Self->{LanguageObject}->Translate("Show Tree Selection"); $Param{MoveQueuesStrg} .= ' ' . $TreeSelectionMessage . ''; } return $Param{MoveQueuesStrg}; } sub TicketListShow { my ( $Self, %Param ) = @_; # take object ref to local, remove it from %Param (prevent memory leak) my $Env = $Param{Env}; delete $Param{Env}; # lookup latest used view mode if ( !$Param{View} && $Self->{ 'UserTicketOverview' . $Env->{Action} } ) { $Param{View} = $Self->{ 'UserTicketOverview' . $Env->{Action} }; } # set default view mode to 'small' my $View = $Param{View} || 'Small'; # set default view mode for AgentTicketQueue or AgentTicketService if ( !$Param{View} && ( $Env->{Action} eq 'AgentTicketQueue' || $Env->{Action} eq 'AgentTicketService' ) ) { $View = 'Preview'; } # store latest view mode $Kernel::OM->Get('Kernel::System::AuthSession')->UpdateSessionID( SessionID => $Self->{SessionID}, Key => 'UserTicketOverview' . $Env->{Action}, Value => $View, ); # get config object my $ConfigObject = $Kernel::OM->Get('Kernel::Config'); # update preferences if needed my $Key = 'UserTicketOverview' . $Env->{Action}; if ( !$ConfigObject->Get('DemoSystem') && ( $Self->{$Key} // '' ) ne $View ) { $Kernel::OM->Get('Kernel::System::User')->SetPreferences( UserID => $Self->{UserID}, Key => $Key, Value => $View, ); } # check backends my $Backends = $ConfigObject->Get('Ticket::Frontend::Overview'); if ( !$Backends ) { return $Self->FatalError( Message => 'Need config option Ticket::Frontend::Overview', ); } if ( ref $Backends ne 'HASH' ) { return $Self->FatalError( Message => 'Config option Ticket::Frontend::Overview need to be HASH ref!', ); } # check if selected view is available if ( !$Backends->{$View} ) { # try to find fallback, take first configured view mode KEY: for my $Key ( sort keys %{$Backends} ) { $Kernel::OM->Get('Kernel::System::Log')->Log( Priority => 'error', Message => "No Config option found for view mode $View, took $Key instead!", ); $View = $Key; last KEY; } } # get layout object my $LayoutObject = $Kernel::OM->Get('Kernel::Output::HTML::Layout'); $LayoutObject->AddJSData( Key => 'View', Value => $View, ); # load overview backend module if ( !$Kernel::OM->Get('Kernel::System::Main')->Require( $Backends->{$View}->{Module} ) ) { return $Env->{LayoutObject}->FatalError(); } my $Object = $Backends->{$View}->{Module}->new( %{$Env} ); return if !$Object; # retireve filter values if ( $Param{FilterContentOnly} ) { return $Object->FilterContent( %Param, ); } # run action row backend module $Param{ActionRow} = $Object->ActionRow( %Param, Config => $Backends->{$View}, ); # run overview backend module $Param{SortOrderBar} = $Object->SortOrderBar( %Param, Config => $Backends->{$View}, ); # check start option, if higher then tickets available, set # it to the last ticket page (Thanks to Stefan Schmidt!) my $StartHit = $Kernel::OM->Get('Kernel::System::Web::Request')->GetParam( Param => 'StartHit' ) || 1; # get personal page shown count my $PageShownPreferencesKey = 'UserTicketOverview' . $View . 'PageShown'; my $PageShown = $Self->{$PageShownPreferencesKey} || 10; my $Group = 'TicketOverview' . $View . 'PageShown'; # get data selection my %Data; my $Config = $ConfigObject->Get('PreferencesGroups'); if ( $Config && $Config->{$Group} && $Config->{$Group}->{Data} ) { %Data = %{ $Config->{$Group}->{Data} }; } # calculate max. shown per page if ( $StartHit > $Param{Total} ) { my $Pages = int( ( $Param{Total} / $PageShown ) + 0.99999 ); $StartHit = ( ( $Pages - 1 ) * $PageShown ) + 1; } # build nav bar my $Limit = $Param{Limit} || 20_000; my %PageNav = $Self->PageNavBar( Limit => $Limit, StartHit => $StartHit, PageShown => $PageShown, AllHits => $Param{Total} || 0, Action => 'Action=' . $Self->{Action}, Link => $Param{LinkPage}, IDPrefix => $Self->{Action}, ); # build shown ticket per page $Param{RequestedURL} = $Param{RequestedURL} || "Action=$Self->{Action}"; $Param{Group} = $Group; $Param{PreferencesKey} = $PageShownPreferencesKey; $Param{PageShownString} = $Self->BuildSelection( Name => $PageShownPreferencesKey, SelectedID => $PageShown, Translation => 0, Data => \%Data, Sort => 'NumericValue', Class => 'Modernize', ); # nav bar at the beginning of a overview $Param{View} = $View; $Self->Block( Name => 'OverviewNavBar', Data => \%Param, ); # back link if ( $Param{LinkBack} ) { $Self->Block( Name => 'OverviewNavBarPageBack', Data => \%Param, ); $LayoutObject->AddJSData( Key => 'Profile', Value => $Param{Profile}, ); } # filter selection if ( $Param{Filters} ) { my @NavBarFilters; for my $Prio ( sort keys %{ $Param{Filters} } ) { push @NavBarFilters, $Param{Filters}->{$Prio}; } $Self->Block( Name => 'OverviewNavBarFilter', Data => { %Param, }, ); my $Count = 0; for my $Filter (@NavBarFilters) { $Count++; if ( $Count == scalar @NavBarFilters ) { $Filter->{CSS} = 'Last'; } $Self->Block( Name => 'OverviewNavBarFilterItem', Data => { %Param, %{$Filter}, }, ); if ( $Filter->{Filter} eq $Param{Filter} ) { $Self->Block( Name => 'OverviewNavBarFilterItemSelected', Data => { %Param, %{$Filter}, }, ); } else { $Self->Block( Name => 'OverviewNavBarFilterItemSelectedNot', Data => { %Param, %{$Filter}, }, ); } } } # view mode for my $Backend ( sort { $Backends->{$a}->{ModulePriority} <=> $Backends->{$b}->{ModulePriority} } keys %{$Backends} ) { $Self->Block( Name => 'OverviewNavBarViewMode', Data => { %Param, %{ $Backends->{$Backend} }, Filter => $Param{Filter}, View => $Backend, }, ); if ( $View eq $Backend ) { $Self->Block( Name => 'OverviewNavBarViewModeSelected', Data => { %Param, %{ $Backends->{$Backend} }, Filter => $Param{Filter}, View => $Backend, }, ); } else { $Self->Block( Name => 'OverviewNavBarViewModeNotSelected', Data => { %Param, %{ $Backends->{$Backend} }, Filter => $Param{Filter}, View => $Backend, }, ); } } if (%PageNav) { $Self->Block( Name => 'OverviewNavBarPageNavBar', Data => \%PageNav, ); # don't show context settings in AJAX case (e. g. in customer ticket history), # because the submit with page reload will not work there if ( !$Param{AJAX} ) { $Self->Block( Name => 'ContextSettings', Data => { %PageNav, %Param, }, ); # show column filter preferences if ( $View eq 'Small' ) { # set preferences keys my $PrefKeyColumns = 'UserFilterColumnsEnabled' . '-' . $Env->{Action}; # create extra needed objects my $JSONObject = $Kernel::OM->Get('Kernel::System::JSON'); # configure columns my @ColumnsEnabled = @{ $Object->{ColumnsEnabled} }; my @ColumnsAvailable; # remove duplicate columns my %UniqueColumns; my @ColumnsEnabledAux; for my $Column (@ColumnsEnabled) { if ( !$UniqueColumns{$Column} ) { push @ColumnsEnabledAux, $Column; } $UniqueColumns{$Column} = 1; } # set filtered column list @ColumnsEnabled = @ColumnsEnabledAux; for my $ColumnName ( sort { $a cmp $b } @{ $Object->{ColumnsAvailable} } ) { if ( !grep { $_ eq $ColumnName } @ColumnsEnabled ) { push @ColumnsAvailable, $ColumnName; } } my %Columns; for my $ColumnName ( sort @ColumnsAvailable ) { $Columns{Columns}->{$ColumnName} = ( grep { $ColumnName eq $_ } @ColumnsEnabled ) ? 1 : 0; } $Self->Block( Name => 'FilterColumnSettings', Data => { Columns => $JSONObject->Encode( Data => \%Columns ), ColumnsEnabled => $JSONObject->Encode( Data => \@ColumnsEnabled ), ColumnsAvailable => $JSONObject->Encode( Data => \@ColumnsAvailable ), NamePref => $PrefKeyColumns, Desc => Translatable('Shown Columns'), Name => $Env->{Action}, View => $View, GroupName => 'TicketOverviewFilterSettings', %Param, }, ); } } # end show column filters preferences # check if there was stored filters, and print a link to delete them if ( IsHashRefWithData( $Object->{StoredFilters} ) ) { $Self->Block( Name => 'DocumentActionRowRemoveColumnFilters', Data => { CSS => "ContextSettings RemoveFilters", %Param, }, ); } } if ( $Param{NavBar} ) { if ( $Param{NavBar}->{MainName} ) { $Self->Block( Name => 'OverviewNavBarMain', Data => $Param{NavBar}, ); } } my $OutputNavBar = $Self->Output( TemplateFile => 'AgentTicketOverviewNavBar', Data => { %Param, }, ); my $OutputRaw = ''; if ( !$Param{Output} ) { $Self->Print( Output => \$OutputNavBar ); } else { $OutputRaw .= $OutputNavBar; } # run overview backend module my $Output = $Object->Run( %Param, Config => $Backends->{$View}, Limit => $Limit, StartHit => $StartHit, PageShown => $PageShown, AllHits => $Param{Total} || 0, Output => $Param{Output} || '', ); if ( !$Param{Output} ) { $Self->Print( Output => \$Output ); } else { $OutputRaw .= $Output; } return $OutputRaw; } sub TicketMetaItemsCount { my ( $Self, %Param ) = @_; return ( 'Priority', 'New Article' ); } sub TicketMetaItems { my ( $Self, %Param ) = @_; if ( ref $Param{Ticket} ne 'HASH' ) { $Self->FatalError( Message => 'Need Hash ref in Ticket param!' ); } # return attributes my @Result; # show priority push @Result, { # Image => $Image, Title => $Param{Ticket}->{Priority}, Class => 'Flag', ClassSpan => 'PriorityID-' . $Param{Ticket}->{PriorityID}, ClassTable => 'Flags', }; # get ticket object my $TicketObject = $Kernel::OM->Get('Kernel::System::Ticket'); my %Ticket = $TicketObject->TicketGet( TicketID => $Param{Ticket}->{TicketID} ); # Show if new message is in there, but show archived tickets as read. my %TicketFlag; if ( $Ticket{ArchiveFlag} ne 'y' ) { %TicketFlag = $TicketObject->TicketFlagGet( TicketID => $Param{Ticket}->{TicketID}, UserID => $Self->{UserID}, ); } if ( $Ticket{ArchiveFlag} eq 'y' || $TicketFlag{Seen} ) { push @Result, undef; } else { # just show ticket flags if agent belongs to the ticket my $ShowMeta; if ( $Self->{UserID} == $Param{Ticket}->{OwnerID} || $Self->{UserID} == $Param{Ticket}->{ResponsibleID} ) { $ShowMeta = 1; } if ( !$ShowMeta && $Kernel::OM->Get('Kernel::Config')->Get('Ticket::Watcher') ) { my %Watch = $TicketObject->TicketWatchGet( TicketID => $Param{Ticket}->{TicketID}, ); if ( $Watch{ $Self->{UserID} } ) { $ShowMeta = 1; } } # show ticket flags my $Image = 'meta-new-inactive.png'; if ($ShowMeta) { $Image = 'meta-new.png'; push @Result, { Image => $Image, Title => Translatable('Unread article(s) available'), Class => 'UnreadArticles', ClassSpan => 'UnreadArticles Remarkable', ClassTable => 'UnreadArticles', }; } else { push @Result, { Image => $Image, Title => Translatable('Unread article(s) available'), Class => 'UnreadArticles', ClassSpan => 'UnreadArticles Ordinary', ClassTable => 'UnreadArticles', }; } } return @Result; } 1; =head1 TERMS AND CONDITIONS This software is part of the OTRS project (L). This software comes with ABSOLUTELY NO WARRANTY. For details, see the enclosed file COPYING for license information (GPL). If you did not receive this file, see L. =cut