1009 lines
33 KiB
Perl
1009 lines
33 KiB
Perl
# --
|
|
# 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::Modules::AgentDashboardCommon;
|
|
## nofilter(TidyAll::Plugin::OTRS::Perl::DBObject)
|
|
|
|
use strict;
|
|
use warnings;
|
|
|
|
use Kernel::Language qw(Translatable);
|
|
use Kernel::System::VariableCheck qw(:all);
|
|
|
|
our $ObjectManagerDisabled = 1;
|
|
|
|
sub new {
|
|
my ( $Type, %Param ) = @_;
|
|
|
|
# allocate new hash for object
|
|
my $Self = {%Param};
|
|
bless( $Self, $Type );
|
|
|
|
return $Self;
|
|
}
|
|
|
|
sub Run {
|
|
my ( $Self, %Param ) = @_;
|
|
|
|
my $BackendConfigKey = 'DashboardBackend';
|
|
my $MainMenuConfigKey = 'AgentDashboard::MainMenu';
|
|
my $UserSettingsKey = 'UserDashboard';
|
|
|
|
if ( $Self->{Action} eq 'AgentCustomerInformationCenter' ) {
|
|
$BackendConfigKey = 'AgentCustomerInformationCenter::Backend';
|
|
$MainMenuConfigKey = 'AgentCustomerInformationCenter::MainMenu';
|
|
$UserSettingsKey = 'UserCustomerInformationCenter';
|
|
}
|
|
elsif ( $Self->{Action} eq 'AgentCustomerUserInformationCenter' ) {
|
|
$BackendConfigKey = 'AgentCustomerUserInformationCenter::Backend';
|
|
$MainMenuConfigKey = 'AgentCustomerUserInformationCenter::MainMenu';
|
|
$UserSettingsKey = 'UserCustomerUserInformationCenter';
|
|
}
|
|
|
|
# get needed objects
|
|
my $ConfigObject = $Kernel::OM->Get('Kernel::Config');
|
|
my $LayoutObject = $Kernel::OM->Get('Kernel::Output::HTML::Layout');
|
|
|
|
# load backends
|
|
my $Config = $ConfigObject->Get($BackendConfigKey);
|
|
if ( !$Config ) {
|
|
return $LayoutObject->ErrorScreen(
|
|
Message => $LayoutObject->{LanguageObject}->Translate( 'No such config for %s', $BackendConfigKey ),
|
|
);
|
|
}
|
|
|
|
# Get all configured statistics from the system that should be shown as a dashboard widget
|
|
# and register them dynamically in the configuration.
|
|
my @StatsIDs;
|
|
if ( $Self->{Action} eq 'AgentDashboard' ) {
|
|
|
|
my $StatsHash = $Kernel::OM->Get('Kernel::System::Stats')->StatsListGet(
|
|
UserID => $Self->{UserID},
|
|
);
|
|
|
|
if ( IsHashRefWithData($StatsHash) ) {
|
|
STATID:
|
|
for my $StatID ( sort keys %{$StatsHash} ) {
|
|
next STATID if !$StatsHash->{$StatID}->{ShowAsDashboardWidget};
|
|
|
|
# check permissions
|
|
next STATID if !$StatsHash->{$StatID}->{Permission};
|
|
next STATID if !IsArrayRefWithData( $StatsHash->{$StatID}->{Permission} );
|
|
|
|
my @StatsPermissionGroupNames;
|
|
for my $GroupID ( @{ $StatsHash->{$StatID}->{Permission} } ) {
|
|
push @StatsPermissionGroupNames,
|
|
$Kernel::OM->Get('Kernel::System::Group')->GroupLookup( GroupID => $GroupID );
|
|
}
|
|
my $StatsPermissionGroups = join( ';', @StatsPermissionGroupNames );
|
|
|
|
# replace all line breaks with spaces (otherwise Translate() will not work correctly)
|
|
$StatsHash->{$StatID}->{Description} =~ s{\r?\n|\r}{ }msxg;
|
|
|
|
my $Description = $LayoutObject->{LanguageObject}->Translate( $StatsHash->{$StatID}->{Description} );
|
|
|
|
my $Title = $LayoutObject->{LanguageObject}->Translate( $StatsHash->{$StatID}->{Title} );
|
|
$Title = $LayoutObject->{LanguageObject}->Translate('Statistic') . ': '
|
|
. $Title . ' ('
|
|
. $ConfigObject->Get('Stats::StatsHook')
|
|
. $StatsHash->{$StatID}->{StatNumber} . ')';
|
|
|
|
$Config->{ ( $StatID + 1000 ) . '-Stats' } = {
|
|
'Block' => 'ContentLarge',
|
|
'Default' => 0,
|
|
'Module' => 'Kernel::Output::HTML::Dashboard::Stats',
|
|
'Title' => $Title,
|
|
'StatID' => $StatID,
|
|
'Description' => $Description,
|
|
'Group' => $StatsPermissionGroups,
|
|
};
|
|
push @StatsIDs, $StatID;
|
|
}
|
|
|
|
# send data to JS
|
|
$LayoutObject->AddJSData(
|
|
Key => 'DashboardStatsIDs',
|
|
Value => \@StatsIDs
|
|
);
|
|
}
|
|
}
|
|
|
|
# get needed objects
|
|
my $ParamObject = $Kernel::OM->Get('Kernel::System::Web::Request');
|
|
|
|
if ( $Self->{Action} eq 'AgentCustomerInformationCenter' ) {
|
|
|
|
$Self->{CustomerID} = $ParamObject->GetParam( Param => 'CustomerID' );
|
|
|
|
# check CustomerID presence for all subactions that need it
|
|
if ( $Self->{Subaction} ne 'UpdatePosition' ) {
|
|
if ( !$Self->{CustomerID} ) {
|
|
|
|
$LayoutObject->AddJSOnDocumentComplete(
|
|
Code => 'Core.Agent.CustomerInformationCenterSearch.OpenSearchDialog();'
|
|
);
|
|
|
|
my $Output = $LayoutObject->Header();
|
|
$Output .= $LayoutObject->NavigationBar();
|
|
$Output .= $LayoutObject->Footer();
|
|
return $Output;
|
|
}
|
|
}
|
|
}
|
|
elsif ( $Self->{Action} eq 'AgentCustomerUserInformationCenter' ) {
|
|
|
|
$Self->{CustomerUserID} = $ParamObject->GetParam( Param => 'CustomerUserID' );
|
|
|
|
# check CustomerUserID presence for all subactions that need it
|
|
if ( $Self->{Subaction} ne 'UpdatePosition' ) {
|
|
|
|
if ( !$Self->{CustomerUserID} ) {
|
|
|
|
$LayoutObject->AddJSOnDocumentComplete(
|
|
Code => 'Core.Agent.CustomerUserInformationCenterSearch.OpenSearchDialog();'
|
|
);
|
|
|
|
my $Output = $LayoutObject->Header();
|
|
$Output .= $LayoutObject->NavigationBar();
|
|
$Output .= $LayoutObject->Footer();
|
|
return $Output;
|
|
}
|
|
}
|
|
}
|
|
|
|
# get needed objects
|
|
my $DynamicFieldObject = $Kernel::OM->Get('Kernel::System::DynamicField');
|
|
my $SessionObject = $Kernel::OM->Get('Kernel::System::AuthSession');
|
|
my $UserObject = $Kernel::OM->Get('Kernel::System::User');
|
|
|
|
# update/close item
|
|
if ( $Self->{Subaction} eq 'UpdateRemove' ) {
|
|
|
|
# challenge token check for write action
|
|
$LayoutObject->ChallengeTokenCheck();
|
|
|
|
my $Name = $ParamObject->GetParam( Param => 'Name' );
|
|
my $Key = $UserSettingsKey . $Name;
|
|
|
|
# Mandatory widgets can't be removed.
|
|
if ( $Config->{$Name} && $Config->{$Name}->{Mandatory} ) {
|
|
|
|
return $LayoutObject->Redirect(
|
|
OP => "Action=$Self->{Action}",
|
|
);
|
|
}
|
|
|
|
# update session
|
|
$SessionObject->UpdateSessionID(
|
|
SessionID => $Self->{SessionID},
|
|
Key => $Key,
|
|
Value => 0,
|
|
);
|
|
|
|
# update preferences
|
|
if ( !$ConfigObject->Get('DemoSystem') ) {
|
|
$UserObject->SetPreferences(
|
|
UserID => $Self->{UserID},
|
|
Key => $Key,
|
|
Value => 0,
|
|
);
|
|
}
|
|
|
|
my $URL = "Action=$Self->{Action}";
|
|
if ( $Self->{CustomerID} ) {
|
|
$URL .= ";CustomerID=" . $LayoutObject->LinkEncode( $Self->{CustomerID} );
|
|
}
|
|
if ( $Self->{CustomerUserID} ) {
|
|
$URL .= ";CustomerUserID=" . $LayoutObject->LinkEncode( $Self->{CustomerUserID} );
|
|
}
|
|
|
|
return $LayoutObject->Redirect(
|
|
OP => $URL,
|
|
);
|
|
}
|
|
|
|
# update preferences
|
|
elsif ( $Self->{Subaction} eq 'UpdatePreferences' ) {
|
|
|
|
# challenge token check for write action
|
|
$LayoutObject->ChallengeTokenCheck();
|
|
|
|
my $Name = $ParamObject->GetParam( Param => 'Name' );
|
|
|
|
# get preferences settings
|
|
my @PreferencesOnly = $Self->_Element(
|
|
Name => $Name,
|
|
Configs => $Config,
|
|
PreferencesOnly => 1,
|
|
);
|
|
if ( !@PreferencesOnly ) {
|
|
$LayoutObject->FatalError(
|
|
Message => $LayoutObject->{LanguageObject}->Translate( 'No preferences for %s!', $Name ),
|
|
);
|
|
}
|
|
|
|
# remember preferences
|
|
for my $Param (@PreferencesOnly) {
|
|
|
|
# get params
|
|
my $Value = $ParamObject->GetParam( Param => $Param->{Name} );
|
|
|
|
# update runtime vars
|
|
$LayoutObject->{ $Param->{Name} } = $Value;
|
|
|
|
# update session
|
|
$SessionObject->UpdateSessionID(
|
|
SessionID => $Self->{SessionID},
|
|
Key => $Param->{Name},
|
|
Value => $Value,
|
|
);
|
|
|
|
# update preferences
|
|
if ( !$ConfigObject->Get('DemoSystem') ) {
|
|
$UserObject->SetPreferences(
|
|
UserID => $Self->{UserID},
|
|
Key => $Param->{Name},
|
|
Value => $Value,
|
|
);
|
|
}
|
|
}
|
|
|
|
# deliver new content page
|
|
my %ElementReload = $Self->_Element(
|
|
Name => $Name,
|
|
Configs => $Config,
|
|
AJAX => 1
|
|
);
|
|
if ( !%ElementReload ) {
|
|
$LayoutObject->FatalError(
|
|
Message => $LayoutObject->{LanguageObject}->Translate( 'Can\'t get element data of %s!', $Name ),
|
|
);
|
|
}
|
|
return $LayoutObject->Attachment(
|
|
ContentType => 'text/html',
|
|
Content => ${ $ElementReload{Content} },
|
|
Type => 'inline',
|
|
NoCache => 1,
|
|
);
|
|
}
|
|
|
|
# update settings
|
|
elsif ( $Self->{Subaction} eq 'UpdateSettings' ) {
|
|
|
|
# challenge token check for write action
|
|
$LayoutObject->ChallengeTokenCheck();
|
|
|
|
my @Backends = $ParamObject->GetArray( Param => 'Backend' );
|
|
for my $Name ( sort keys %{$Config} ) {
|
|
my $Active = 0;
|
|
BACKEND:
|
|
for my $Backend (@Backends) {
|
|
next BACKEND if $Backend ne $Name;
|
|
$Active = 1;
|
|
last BACKEND;
|
|
}
|
|
|
|
# Mandatory widgets can not be removed.
|
|
if ( $Config->{$Name}->{Mandatory} ) {
|
|
$Active = 1;
|
|
}
|
|
|
|
my $Key = $UserSettingsKey . $Name;
|
|
|
|
# update session
|
|
$SessionObject->UpdateSessionID(
|
|
SessionID => $Self->{SessionID},
|
|
Key => $Key,
|
|
Value => $Active,
|
|
);
|
|
|
|
# update preferences
|
|
if ( !$ConfigObject->Get('DemoSystem') ) {
|
|
$UserObject->SetPreferences(
|
|
UserID => $Self->{UserID},
|
|
Key => $Key,
|
|
Value => $Active,
|
|
);
|
|
}
|
|
}
|
|
|
|
my $URL = "Action=$Self->{Action}";
|
|
if ( $Self->{CustomerID} ) {
|
|
$URL .= ";CustomerID=" . $LayoutObject->LinkEncode( $Self->{CustomerID} );
|
|
}
|
|
if ( $Self->{CustomerUserID} ) {
|
|
$URL .= ";CustomerUserID=" . $LayoutObject->LinkEncode( $Self->{CustomerUserID} );
|
|
}
|
|
|
|
return $LayoutObject->Redirect(
|
|
OP => $URL,
|
|
);
|
|
}
|
|
|
|
# update position
|
|
elsif ( $Self->{Subaction} eq 'UpdatePosition' ) {
|
|
|
|
# challenge token check for write action
|
|
$LayoutObject->ChallengeTokenCheck();
|
|
|
|
my @Backends = $ParamObject->GetArray( Param => 'Backend' );
|
|
|
|
# get new order
|
|
my $Key = $UserSettingsKey . 'Position';
|
|
my $Data = '';
|
|
for my $Backend (@Backends) {
|
|
$Backend =~ s{ \A Dashboard (.+?) -box \z }{$1}gxms;
|
|
$Data .= $Backend . ';';
|
|
}
|
|
|
|
# update session
|
|
$SessionObject->UpdateSessionID(
|
|
SessionID => $Self->{SessionID},
|
|
Key => $Key,
|
|
Value => $Data,
|
|
);
|
|
|
|
# update preferences
|
|
if ( !$ConfigObject->Get('DemoSystem') ) {
|
|
$UserObject->SetPreferences(
|
|
UserID => $Self->{UserID},
|
|
Key => $Key,
|
|
Value => $Data,
|
|
);
|
|
}
|
|
|
|
# send successful response
|
|
return $LayoutObject->Attachment(
|
|
ContentType => 'text/html',
|
|
Charset => $LayoutObject->{UserCharset},
|
|
Content => '1',
|
|
);
|
|
}
|
|
|
|
# deliver element
|
|
elsif ( $Self->{Subaction} eq 'Element' ) {
|
|
|
|
my $Name = $ParamObject->GetParam( Param => 'Name' );
|
|
|
|
# get the column filters from the web request
|
|
my %ColumnFilter;
|
|
my %GetColumnFilter;
|
|
my %GetColumnFilterSelect;
|
|
|
|
COLUMNNAME:
|
|
for my $ColumnName (
|
|
qw(Owner Responsible State Queue Priority Type Lock Service SLA CustomerID CustomerUserID)
|
|
)
|
|
{
|
|
my $FilterValue = $ParamObject->GetParam( Param => 'ColumnFilter' . $ColumnName . $Name )
|
|
|| '';
|
|
next COLUMNNAME if $FilterValue eq '';
|
|
|
|
if ( $ColumnName eq 'CustomerID' ) {
|
|
push @{ $ColumnFilter{$ColumnName} }, $FilterValue;
|
|
push @{ $ColumnFilter{ $ColumnName . 'Raw' } }, $FilterValue;
|
|
}
|
|
elsif ( $ColumnName eq 'CustomerUserID' ) {
|
|
push @{ $ColumnFilter{CustomerUserLogin} }, $FilterValue;
|
|
push @{ $ColumnFilter{CustomerUserLoginRaw} }, $FilterValue;
|
|
}
|
|
else {
|
|
push @{ $ColumnFilter{ $ColumnName . 'IDs' } }, $FilterValue;
|
|
}
|
|
|
|
$GetColumnFilter{ $ColumnName . $Name } = $FilterValue;
|
|
$GetColumnFilterSelect{$ColumnName} = $FilterValue;
|
|
}
|
|
|
|
# get all dynamic fields
|
|
my $DynamicField = $DynamicFieldObject->DynamicFieldListGet(
|
|
Valid => 1,
|
|
ObjectType => ['Ticket'],
|
|
);
|
|
|
|
DYNAMICFIELD:
|
|
for my $DynamicFieldConfig ( @{$DynamicField} ) {
|
|
next DYNAMICFIELD if !IsHashRefWithData($DynamicFieldConfig);
|
|
next DYNAMICFIELD if !$DynamicFieldConfig->{Name};
|
|
|
|
my $FilterValue = $ParamObject->GetParam(
|
|
Param => 'ColumnFilterDynamicField_' . $DynamicFieldConfig->{Name} . $Name
|
|
);
|
|
|
|
next DYNAMICFIELD if !defined $FilterValue;
|
|
next DYNAMICFIELD if $FilterValue eq '';
|
|
|
|
$ColumnFilter{ 'DynamicField_' . $DynamicFieldConfig->{Name} } = {
|
|
Equals => $FilterValue,
|
|
};
|
|
$GetColumnFilter{ 'DynamicField_' . $DynamicFieldConfig->{Name} . $Name } = $FilterValue;
|
|
$GetColumnFilterSelect{ 'DynamicField_' . $DynamicFieldConfig->{Name} } = $FilterValue;
|
|
}
|
|
|
|
my $SortBy = $ParamObject->GetParam( Param => 'SortBy' );
|
|
my $OrderBy = $ParamObject->GetParam( Param => 'OrderBy' );
|
|
|
|
my %Element = $Self->_Element(
|
|
Name => $Name,
|
|
Configs => $Config,
|
|
AJAX => 1,
|
|
SortBy => $SortBy,
|
|
OrderBy => $OrderBy,
|
|
ColumnFilter => \%ColumnFilter,
|
|
GetColumnFilter => \%GetColumnFilter,
|
|
GetColumnFilterSelect => \%GetColumnFilterSelect,
|
|
);
|
|
|
|
if ( !%Element ) {
|
|
$LayoutObject->FatalError(
|
|
Message => $LayoutObject->{LanguageObject}->Translate( 'Can\'t get element data of %s!', $Name ),
|
|
);
|
|
}
|
|
return $LayoutObject->Attachment(
|
|
ContentType => 'text/html',
|
|
Charset => $LayoutObject->{UserCharset},
|
|
Content => ${ $Element{Content} },
|
|
Type => 'inline',
|
|
NoCache => 1,
|
|
);
|
|
}
|
|
|
|
# deliver element
|
|
elsif ( $Self->{Subaction} eq 'AJAXFilterUpdate' ) {
|
|
|
|
my $ElementChanged = $ParamObject->GetParam( Param => 'ElementChanged' );
|
|
my ($Name) = $ElementChanged =~ m{ ( \d{4} - .*? ) \z }gxms;
|
|
my $Column = $ElementChanged;
|
|
$Column =~ s{ \A ColumnFilter }{}gxms;
|
|
$Column =~ s{ $Name }{}gxms;
|
|
|
|
my $FilterContent = $Self->_Element(
|
|
Name => $Name,
|
|
FilterContentOnly => 1,
|
|
FilterColumn => $Column,
|
|
ElementChanged => $ElementChanged,
|
|
Configs => $Config,
|
|
);
|
|
|
|
if ( !$FilterContent ) {
|
|
$LayoutObject->FatalError(
|
|
Message => $LayoutObject->{LanguageObject}->Translate( 'Can\'t get filter content data of %s!', $Name ),
|
|
);
|
|
}
|
|
|
|
return $LayoutObject->Attachment(
|
|
ContentType => 'application/json; charset=' . $LayoutObject->{Charset},
|
|
Content => $FilterContent,
|
|
Type => 'inline',
|
|
NoCache => 1,
|
|
);
|
|
|
|
}
|
|
|
|
# store last queue screen
|
|
$SessionObject->UpdateSessionID(
|
|
SessionID => $Self->{SessionID},
|
|
Key => 'LastScreenOverview',
|
|
Value => $Self->{RequestedURL},
|
|
);
|
|
|
|
my %ContentBlockData;
|
|
|
|
if ( $Self->{Action} eq 'AgentCustomerInformationCenter' ) {
|
|
|
|
$ContentBlockData{CustomerID} = $Self->{CustomerID};
|
|
|
|
# H1 title
|
|
$ContentBlockData{CustomerIDTitle} = $Self->{CustomerID};
|
|
|
|
my %CustomerCompanyData = $Kernel::OM->Get('Kernel::System::CustomerCompany')->CustomerCompanyGet(
|
|
CustomerID => $Self->{CustomerID},
|
|
);
|
|
|
|
if ( $CustomerCompanyData{CustomerCompanyName} ) {
|
|
$ContentBlockData{CustomerIDTitle} = "$CustomerCompanyData{CustomerCompanyName} ($Self->{CustomerID})";
|
|
}
|
|
}
|
|
elsif ( $Self->{Action} eq 'AgentCustomerUserInformationCenter' ) {
|
|
|
|
my %CustomerUserData = $Kernel::OM->Get('Kernel::System::CustomerUser')->CustomerUserDataGet(
|
|
User => $Self->{CustomerUserID},
|
|
);
|
|
|
|
$ContentBlockData{CustomerUserID} = $Self->{CustomerUserID};
|
|
|
|
# H1 title
|
|
$ContentBlockData{CustomerUserIDTitle} = "\"$CustomerUserData{UserFullname}\" <$CustomerUserData{UserEmail}>";
|
|
|
|
}
|
|
|
|
# show dashboard
|
|
$LayoutObject->Block(
|
|
Name => 'Content',
|
|
Data => \%ContentBlockData,
|
|
);
|
|
|
|
my $GroupObject = $Kernel::OM->Get('Kernel::System::Group');
|
|
|
|
# get shown backends
|
|
my %Backends;
|
|
BACKEND:
|
|
for my $Name ( sort keys %{$Config} ) {
|
|
|
|
# check permissions
|
|
if ( $Config->{$Name}->{Group} ) {
|
|
my $PermissionOK = 0;
|
|
my @Groups = split /;/, $Config->{$Name}->{Group};
|
|
GROUP:
|
|
for my $Group (@Groups) {
|
|
my $HasPermission = $GroupObject->PermissionCheck(
|
|
UserID => $Self->{UserID},
|
|
GroupName => $Group,
|
|
Type => 'ro',
|
|
);
|
|
if ($HasPermission) {
|
|
$PermissionOK = 1;
|
|
last GROUP;
|
|
}
|
|
}
|
|
next BACKEND if !$PermissionOK;
|
|
}
|
|
|
|
my $Key = $UserSettingsKey . $Name;
|
|
if ( defined $Self->{$Key} ) {
|
|
$Backends{$Name} = $Self->{$Key};
|
|
}
|
|
else {
|
|
$Backends{$Name} = $Config->{$Name}->{Default};
|
|
}
|
|
|
|
# Always show widgets with mandatory flag.
|
|
if ( $Config->{$Name}->{Mandatory} ) {
|
|
$Backends{$Name} = $Config->{$Name}->{Mandatory};
|
|
}
|
|
}
|
|
|
|
# set order of plugins
|
|
my $Key = $UserSettingsKey . 'Position';
|
|
my @Order;
|
|
my $Value = $Self->{$Key};
|
|
|
|
if ($Value) {
|
|
@Order = split /;/, $Value;
|
|
|
|
# only use active backends
|
|
@Order = grep { $Config->{$_} } @Order;
|
|
}
|
|
if ( !@Order ) {
|
|
for my $Name ( sort keys %Backends ) {
|
|
push @Order, $Name;
|
|
}
|
|
}
|
|
|
|
# add not ordered plugins (e. g. new active)
|
|
NAME:
|
|
for my $Name ( sort keys %Backends ) {
|
|
my $Included = 0;
|
|
ITEM:
|
|
for my $Item (@Order) {
|
|
next ITEM if $Item ne $Name;
|
|
$Included = 1;
|
|
}
|
|
next NAME if $Included;
|
|
push @Order, $Name;
|
|
}
|
|
|
|
# get default columns
|
|
my $Columns = $Self->{Config}->{DefaultColumns} || $ConfigObject->Get('DefaultOverviewColumns') || {};
|
|
|
|
# try every backend to load and execute it
|
|
my @ContainerNames;
|
|
NAME:
|
|
for my $Name (@Order) {
|
|
|
|
# get element data
|
|
my %Element = $Self->_Element(
|
|
Name => $Name,
|
|
Configs => $Config,
|
|
Backends => \%Backends,
|
|
);
|
|
next NAME if !%Element;
|
|
|
|
# NameForm (to support IE, is not working with "-" in form names)
|
|
my $NameForm = $Name;
|
|
$NameForm =~ s{-}{}g;
|
|
|
|
my %JSData = (
|
|
Name => $Name,
|
|
NameForm => $NameForm,
|
|
);
|
|
|
|
push @ContainerNames, \%JSData;
|
|
|
|
# rendering
|
|
$LayoutObject->Block(
|
|
Name => $Element{Config}->{Block},
|
|
Data => {
|
|
%{ $Element{Config} },
|
|
Name => $Name,
|
|
NameForm => $NameForm,
|
|
Content => ${ $Element{Content} },
|
|
CustomerID => $Self->{CustomerID} || '',
|
|
CustomerUserID => $Self->{CustomerUserID} || '',
|
|
},
|
|
);
|
|
|
|
# show refresh link if refreshing is available
|
|
if ( $Element{Config}->{CanRefresh} ) {
|
|
|
|
my $NameHTML = $Name;
|
|
$NameHTML =~ s{-}{_}xmsg;
|
|
|
|
# send data to JS
|
|
$LayoutObject->AddJSData(
|
|
Key => 'CanRefresh-' . $Name,
|
|
Value => {
|
|
Name => $Name,
|
|
NameHTML => $NameHTML,
|
|
}
|
|
);
|
|
|
|
$LayoutObject->Block(
|
|
Name => $Element{Config}->{Block} . 'Refresh',
|
|
Data => {
|
|
%{ $Element{Config} },
|
|
Name => $Name,
|
|
NameHTML => $NameHTML,
|
|
},
|
|
);
|
|
}
|
|
|
|
# Do not show the delete link if the widget is mandatory.
|
|
if ( !$Config->{$Name}->{Mandatory} ) {
|
|
|
|
$LayoutObject->Block(
|
|
Name => $Element{Config}->{Block} . 'Remove',
|
|
Data => {
|
|
%{ $Element{Config} },
|
|
Name => $Name,
|
|
CustomerID => $Self->{CustomerID} || '',
|
|
CustomerUserID => $Self->{CustomerUserID} || '',
|
|
},
|
|
);
|
|
}
|
|
|
|
# if column is not a default column, add it for translation
|
|
for my $Column ( sort keys %{ $Element{Config}->{DefaultColumns} } ) {
|
|
if ( !defined $Columns->{$Column} ) {
|
|
$Columns->{$Column} = $Element{Config}->{DefaultColumns}->{$Column};
|
|
}
|
|
}
|
|
|
|
# show settings link if preferences are available
|
|
if ( $Element{Preferences} && @{ $Element{Preferences} } ) {
|
|
$LayoutObject->Block(
|
|
Name => $Element{Config}->{Block} . 'Preferences',
|
|
Data => {
|
|
%{ $Element{Config} },
|
|
Name => $Name,
|
|
NameForm => $NameForm,
|
|
},
|
|
);
|
|
PARAM:
|
|
for my $Param ( @{ $Element{Preferences} } ) {
|
|
|
|
# special parameters are added, which do not have a tt block,
|
|
# because the displayed fields are added with the output filter,
|
|
# so there is no need to call any block here
|
|
next PARAM if !$Param->{Block};
|
|
|
|
$LayoutObject->Block(
|
|
Name => $Element{Config}->{Block} . 'PreferencesItem',
|
|
Data => {
|
|
%{ $Element{Config} },
|
|
Name => $Name,
|
|
NameForm => $NameForm,
|
|
},
|
|
);
|
|
if ( $Param->{Block} eq 'Option' ) {
|
|
$Param->{Option} = $LayoutObject->BuildSelection(
|
|
Data => $Param->{Data},
|
|
Name => $Param->{Name},
|
|
SelectedID => $Param->{SelectedID},
|
|
Translation => $Param->{Translation},
|
|
Class => 'Modernize',
|
|
);
|
|
}
|
|
$LayoutObject->Block(
|
|
Name => $Element{Config}->{Block} . 'PreferencesItem' . $Param->{Block},
|
|
Data => {
|
|
%{ $Element{Config} },
|
|
%{$Param},
|
|
Data => $Self->{ $Param->{Name} },
|
|
NamePref => $Param->{Name},
|
|
Name => $Name,
|
|
NameForm => $NameForm,
|
|
},
|
|
);
|
|
}
|
|
}
|
|
|
|
# more link
|
|
if ( $Element{Config}->{Link} ) {
|
|
$LayoutObject->Block(
|
|
Name => $Element{Config}->{Block} . 'More',
|
|
Data => {
|
|
%{ $Element{Config} },
|
|
},
|
|
);
|
|
}
|
|
}
|
|
|
|
# send data to JS
|
|
$LayoutObject->AddJSData(
|
|
Key => 'ContainerNames',
|
|
Value => \@ContainerNames,
|
|
);
|
|
|
|
# build main menu
|
|
my $MainMenuConfig = $ConfigObject->Get($MainMenuConfigKey);
|
|
if ( IsHashRefWithData($MainMenuConfig) ) {
|
|
$LayoutObject->Block( Name => 'MainMenu' );
|
|
|
|
for my $MainMenuItem ( sort keys %{$MainMenuConfig} ) {
|
|
|
|
$LayoutObject->Block(
|
|
Name => 'MainMenuItem',
|
|
Data => {
|
|
%{ $MainMenuConfig->{$MainMenuItem} },
|
|
CustomerID => $Self->{CustomerID},
|
|
CustomerUserID => $Self->{CustomerUserID},
|
|
},
|
|
);
|
|
}
|
|
}
|
|
|
|
# add translations for the allocation lists for regular columns
|
|
if ( $Columns && IsHashRefWithData($Columns) ) {
|
|
|
|
COLUMN:
|
|
for my $Column ( sort keys %{$Columns} ) {
|
|
|
|
# dynamic fields will be translated in the next block
|
|
next COLUMN if $Column =~ m{ \A DynamicField_ }xms;
|
|
|
|
my $TranslatedWord = $Column;
|
|
if ( $Column eq 'EscalationTime' ) {
|
|
$TranslatedWord = Translatable('Service Time');
|
|
}
|
|
elsif ( $Column eq 'EscalationResponseTime' ) {
|
|
$TranslatedWord = Translatable('First Response Time');
|
|
}
|
|
elsif ( $Column eq 'EscalationSolutionTime' ) {
|
|
$TranslatedWord = Translatable('Solution Time');
|
|
}
|
|
elsif ( $Column eq 'EscalationUpdateTime' ) {
|
|
$TranslatedWord = Translatable('Update Time');
|
|
}
|
|
elsif ( $Column eq 'PendingTime' ) {
|
|
$TranslatedWord = Translatable('Pending till');
|
|
}
|
|
elsif ( $Column eq 'CustomerCompanyName' ) {
|
|
$TranslatedWord = Translatable('Customer Name');
|
|
}
|
|
elsif ( $Column eq 'CustomerID' ) {
|
|
$TranslatedWord = Translatable('Customer ID');
|
|
}
|
|
elsif ( $Column eq 'CustomerName' ) {
|
|
$TranslatedWord = Translatable('Customer User Name');
|
|
}
|
|
elsif ( $Column eq 'CustomerUserID' ) {
|
|
$TranslatedWord = Translatable('Customer User ID');
|
|
}
|
|
|
|
# send data to JS
|
|
$LayoutObject->AddJSData(
|
|
Key => 'Column' . $Column,
|
|
Value => $LayoutObject->{LanguageObject}->Translate($TranslatedWord),
|
|
);
|
|
|
|
}
|
|
}
|
|
|
|
# add translations for the allocation lists for dynamic field columns
|
|
my $ColumnsDynamicField = $DynamicFieldObject->DynamicFieldListGet(
|
|
Valid => 0,
|
|
ObjectType => ['Ticket'],
|
|
);
|
|
|
|
if ( $ColumnsDynamicField && IsArrayRefWithData($ColumnsDynamicField) ) {
|
|
|
|
my $Counter = 0;
|
|
|
|
DYNAMICFIELD:
|
|
for my $DynamicField ( sort @{$ColumnsDynamicField} ) {
|
|
|
|
next DYNAMICFIELD if !$DynamicField;
|
|
|
|
$Counter++;
|
|
|
|
# send data to JS
|
|
$LayoutObject->AddJSData(
|
|
Key => 'ColumnDynamicField_' . $DynamicField->{Name},
|
|
Value => $LayoutObject->{LanguageObject}->Translate( $DynamicField->{Label} ),
|
|
);
|
|
}
|
|
}
|
|
|
|
my $Output = $LayoutObject->Header();
|
|
$Output .= $LayoutObject->NavigationBar();
|
|
$Output .= $LayoutObject->Output(
|
|
TemplateFile => $Self->{Action},
|
|
Data => \%Param
|
|
);
|
|
$Output .= $LayoutObject->Footer();
|
|
return $Output;
|
|
}
|
|
|
|
sub _Element {
|
|
my ( $Self, %Param ) = @_;
|
|
|
|
my $Name = $Param{Name};
|
|
my $Configs = $Param{Configs};
|
|
my $Backends = $Param{Backends};
|
|
my $SortBy = $Param{SortBy};
|
|
my $OrderBy = $Param{OrderBy};
|
|
my $ColumnFilter = $Param{ColumnFilter};
|
|
my $GetColumnFilter = $Param{GetColumnFilter};
|
|
my $GetColumnFilterSelect = $Param{GetColumnFilterSelect};
|
|
|
|
my $GroupObject = $Kernel::OM->Get('Kernel::System::Group');
|
|
|
|
# check permissions
|
|
if ( $Configs->{$Name}->{Group} ) {
|
|
my $PermissionOK = 0;
|
|
my @Groups = split /;/, $Configs->{$Name}->{Group};
|
|
GROUP:
|
|
for my $Group (@Groups) {
|
|
my $HasPermission = $GroupObject->PermissionCheck(
|
|
UserID => $Self->{UserID},
|
|
GroupName => $Group,
|
|
Type => 'ro',
|
|
);
|
|
if ($HasPermission) {
|
|
$PermissionOK = 1;
|
|
last GROUP;
|
|
}
|
|
}
|
|
return if !$PermissionOK;
|
|
}
|
|
|
|
# get config object
|
|
my $ConfigObject = $Kernel::OM->Get('Kernel::Config');
|
|
|
|
# load backends
|
|
my $Module = $Configs->{$Name}->{Module};
|
|
return if !$Kernel::OM->Get('Kernel::System::Main')->Require($Module);
|
|
my $Object = $Module->new(
|
|
%{$Self},
|
|
Config => $Configs->{$Name},
|
|
Name => $Name,
|
|
CustomerID => $Self->{CustomerID} || '',
|
|
CustomerUserID => $Self->{CustomerUserID} || '',
|
|
SortBy => $SortBy,
|
|
OrderBy => $OrderBy,
|
|
ColumnFilter => $ColumnFilter,
|
|
GetColumnFilter => $GetColumnFilter,
|
|
GetColumnFilterSelect => $GetColumnFilterSelect,
|
|
);
|
|
|
|
# get module config
|
|
my %Config = $Object->Config();
|
|
|
|
# Perform the actual data fetching and computation on the slave db, if configured
|
|
local $Kernel::System::DB::UseSlaveDB = 1;
|
|
|
|
# get module preferences
|
|
my @Preferences = $Object->Preferences();
|
|
return @Preferences if $Param{PreferencesOnly};
|
|
|
|
# Perform the actual data fetching and computation on the slave db, if configured
|
|
local $Kernel::System::DB::UseSlaveDB = 1;
|
|
|
|
if ( $Param{FilterContentOnly} ) {
|
|
my $FilterContent = $Object->FilterContent(
|
|
FilterColumn => $Param{FilterColumn},
|
|
Config => $Configs->{$Name},
|
|
Name => $Name,
|
|
CustomerID => $Self->{CustomerID} || '',
|
|
CustomerUserID => $Self->{CustomerUserID} || '',
|
|
);
|
|
return $FilterContent;
|
|
}
|
|
|
|
my $LayoutObject = $Kernel::OM->Get('Kernel::Output::HTML::Layout');
|
|
|
|
# add backend to settings selection
|
|
if ($Backends) {
|
|
my $Checked = '';
|
|
if ( $Backends->{$Name} || $Configs->{$Name}->{Mandatory} ) {
|
|
$Checked = 'checked="checked"';
|
|
}
|
|
|
|
# Check whether the widget is forcibly displayed.
|
|
# Mandatory widgets are displayed as read-only.
|
|
my $Readonly = '';
|
|
if ( $Configs->{$Name}->{Mandatory} ) {
|
|
$Readonly = 'disabled="disabled"';
|
|
}
|
|
|
|
$LayoutObject->Block(
|
|
Name => 'ContentSettings',
|
|
Data => {
|
|
%Config,
|
|
Name => $Name,
|
|
Checked => $Checked,
|
|
Readonly => $Readonly,
|
|
},
|
|
);
|
|
|
|
return if !$Backends->{$Name};
|
|
}
|
|
|
|
# check backends cache (html page cache)
|
|
my $Content;
|
|
my $CacheKey = $Config{CacheKey};
|
|
my $CacheObject = $Kernel::OM->Get('Kernel::System::Cache');
|
|
|
|
if ( !$CacheKey ) {
|
|
$CacheKey = $Name . '-'
|
|
. ( $Self->{CustomerID} || '' ) . '-'
|
|
. ( $Self->{CustomerUserID} || '' ) . '-'
|
|
. $LayoutObject->{UserLanguage};
|
|
}
|
|
if ( $Config{CacheTTL} ) {
|
|
$Content = $CacheObject->Get(
|
|
Type => 'Dashboard',
|
|
Key => $CacheKey,
|
|
);
|
|
}
|
|
|
|
# execute backends
|
|
my $CacheUsed = 1;
|
|
if ( !defined $Content || $SortBy ) {
|
|
$CacheUsed = 0;
|
|
$Content = $Object->Run(
|
|
AJAX => $Param{AJAX},
|
|
CustomerID => $Self->{CustomerID} || '',
|
|
CustomerUserID => $Self->{CustomerUserID} || '',
|
|
);
|
|
}
|
|
|
|
# check if content should be shown
|
|
return if !$Content;
|
|
|
|
# set cache (html page cache)
|
|
if ( !$CacheUsed && $Config{CacheTTL} ) {
|
|
$CacheObject->Set(
|
|
Type => 'Dashboard',
|
|
Key => $CacheKey,
|
|
Value => $Content,
|
|
TTL => $Config{CacheTTL} * 60,
|
|
);
|
|
}
|
|
|
|
# return result
|
|
return (
|
|
Content => \$Content,
|
|
Config => \%Config,
|
|
Preferences => \@Preferences,
|
|
);
|
|
}
|
|
|
|
1;
|