895 lines
27 KiB
Perl
895 lines
27 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::Output::HTML::Dashboard::ITSMConfigItemGeneric;
|
|
|
|
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 );
|
|
|
|
# Get needed parameters.
|
|
for my $Needed (qw(Config Name UserID)) {
|
|
die "Got no $Needed!" if ( !$Self->{$Needed} );
|
|
}
|
|
|
|
# Get param object.
|
|
my $ParamObject = $Kernel::OM->Get('Kernel::System::Web::Request');
|
|
|
|
# Get current filter.
|
|
my $Name = $ParamObject->GetParam( Param => 'Name' ) || '';
|
|
my $PreferencesKey = 'DashboardITSMConfigItemGeneric' . $Self->{Name};
|
|
if ( $Self->{Name} eq $Name ) {
|
|
$Self->{Filter} = $ParamObject->GetParam( Param => 'Filter' ) || '';
|
|
}
|
|
|
|
# Get config object.
|
|
my $ConfigObject = $Kernel::OM->Get('Kernel::Config');
|
|
|
|
# Remember filter.
|
|
if ( $Self->{Filter} ) {
|
|
|
|
# Update session.
|
|
$Kernel::OM->Get('Kernel::System::AuthSession')->UpdateSessionID(
|
|
SessionID => $Self->{SessionID},
|
|
Key => $PreferencesKey,
|
|
Value => $Self->{Filter},
|
|
);
|
|
|
|
# Update preferences.
|
|
if ( !$ConfigObject->Get('DemoSystem') ) {
|
|
$Kernel::OM->Get('Kernel::System::User')->SetPreferences(
|
|
UserID => $Self->{UserID},
|
|
Key => $PreferencesKey,
|
|
Value => $Self->{Filter},
|
|
);
|
|
}
|
|
}
|
|
|
|
# Set default filter if not set yet.
|
|
if ( !$Self->{Filter} ) {
|
|
$Self->{Filter} = $Self->{$PreferencesKey} || $Self->{Config}->{Filter} || 'All';
|
|
}
|
|
|
|
# Setup the prefrences keys.
|
|
$Self->{PrefKeyShown} = 'DashboardITSMConfigItemGeneric' . $Self->{Name} . '-Shown';
|
|
$Self->{PrefKeyRefresh} = 'DashboardITSMConfigItemGeneric' . $Self->{Name} . '-Refresh';
|
|
|
|
$Self->{PageShown} = $Kernel::OM->Get('Kernel::Output::HTML::Layout')->{ $Self->{PrefKeyShown} }
|
|
|| $Self->{Config}->{Limit} || 10;
|
|
|
|
$Self->{PageRefresh} = $Kernel::OM->Get('Kernel::Output::HTML::Layout')->{ $Self->{PrefKeyRefresh} }
|
|
|| 1;
|
|
|
|
$Self->{StartHit} = int( $ParamObject->GetParam( Param => 'StartHit' ) || 1 );
|
|
|
|
return $Self;
|
|
}
|
|
|
|
sub Preferences {
|
|
my ( $Self, %Param ) = @_;
|
|
|
|
my @Params = (
|
|
{
|
|
Desc => Translatable('Shown config items'),
|
|
Name => $Self->{PrefKeyShown},
|
|
Block => 'Option',
|
|
Data => {
|
|
5 => ' 5',
|
|
10 => '10',
|
|
15 => '15',
|
|
20 => '20',
|
|
25 => '25',
|
|
30 => '30',
|
|
},
|
|
SelectedID => $Self->{PageShown},
|
|
Translation => 0,
|
|
},
|
|
);
|
|
|
|
return @Params;
|
|
}
|
|
|
|
sub Config {
|
|
my ( $Self, %Param ) = @_;
|
|
|
|
return (
|
|
%{ $Self->{Config} },
|
|
|
|
# Remember, do not allow to use page cache
|
|
# (it's not working because of internal filter)
|
|
CacheKey => undef,
|
|
CacheTTL => undef,
|
|
);
|
|
}
|
|
|
|
sub Run {
|
|
my ( $Self, %Param ) = @_;
|
|
|
|
# Get param object.
|
|
my $ParamObject = $Kernel::OM->Get('Kernel::System::Web::Request');
|
|
|
|
# Get layout object.
|
|
my $LayoutObject = $Kernel::OM->Get('Kernel::Output::HTML::Layout');
|
|
|
|
# Get sorting parameters.
|
|
$Param{SortBy} = $ParamObject->GetParam( Param => 'SortBy' ) || 'Number';
|
|
|
|
# Get ordering parameters.
|
|
$Param{OrderBy} = $ParamObject->GetParam( Param => 'OrderBy' ) || 'Up';
|
|
|
|
# Set Sort and Order by as Arrays.
|
|
my @SortByArray = ( $Param{SortBy} );
|
|
my @OrderByArray = ( $Param{OrderBy} );
|
|
|
|
# Get general catalog object.
|
|
my $GeneralCatalogObject = $Kernel::OM->Get('Kernel::System::GeneralCatalog');
|
|
|
|
# Get class list.
|
|
my $ClassList = $GeneralCatalogObject->ItemList(
|
|
Class => 'ITSM::ConfigItem::Class',
|
|
);
|
|
|
|
# To store the color for the deployment states.
|
|
my %DeplSignals;
|
|
|
|
# Get list of deployment states.
|
|
my $DeploymentStatesList = $GeneralCatalogObject->ItemList(
|
|
Class => 'ITSM::ConfigItem::DeploymentState',
|
|
);
|
|
|
|
# Set deployment style colors.
|
|
my $StyleClasses = '';
|
|
|
|
# To store depl state ids.
|
|
my $DeplStateIDs;
|
|
|
|
ITEMID:
|
|
for my $ItemID ( sort keys %{$DeploymentStatesList} ) {
|
|
|
|
# Get deployment state preferences.
|
|
my %Preferences = $GeneralCatalogObject->GeneralCatalogPreferencesGet(
|
|
ItemID => $ItemID,
|
|
);
|
|
|
|
# Check if a color is defined in preferences.
|
|
next ITEMID if !$Preferences{Color};
|
|
|
|
# Get deployment state.
|
|
my $DeplState = $DeploymentStatesList->{$ItemID};
|
|
|
|
# Remove any non ascii word characters.
|
|
$DeplState =~ s{ [^a-zA-Z0-9] }{_}msxg;
|
|
|
|
# Store the original deployment state as key
|
|
# and the ss safe coverted deployment state as value.
|
|
$DeplSignals{ $DeploymentStatesList->{$ItemID} } = $DeplState;
|
|
|
|
# Convert to lower case.
|
|
my $DeplStateColor = lc $Preferences{Color};
|
|
|
|
# Add to style classes string.
|
|
$StyleClasses .= "
|
|
.Flag span.$DeplState {
|
|
background-color: #$DeplStateColor;
|
|
}
|
|
";
|
|
|
|
# Set depl state ids.
|
|
push @{$DeplStateIDs}, $ItemID;
|
|
}
|
|
|
|
# Wrap into style tags.
|
|
if ($StyleClasses) {
|
|
$StyleClasses = "<style>$StyleClasses</style>";
|
|
}
|
|
|
|
# To store the default class.
|
|
my $ClassIDAuto = '';
|
|
|
|
# To store the NavBar filters.
|
|
my %Filters;
|
|
|
|
# Define position of the filter in the frontend.
|
|
my $PrioCounter = 1000;
|
|
|
|
# To store the total number of config items in all classes that the user has access.
|
|
my $TotalCount;
|
|
|
|
# To store all the clases that the user has access, used in search for filter 'All'.
|
|
my $AccessClassList;
|
|
|
|
# Get config item object.
|
|
my $ConfigItemObject = $Kernel::OM->Get('Kernel::System::ITSMConfigItem');
|
|
|
|
# Define incident signals, needed for services.
|
|
my %InciSignals = (
|
|
Translatable('operational') => 'greenled',
|
|
Translatable('warning') => 'yellowled',
|
|
Translatable('incident') => 'redled',
|
|
);
|
|
|
|
CLASSID:
|
|
for my $ClassID ( sort { ${$ClassList}{$a} cmp ${$ClassList}{$b} } keys %{$ClassList} ) {
|
|
|
|
# Check permission.
|
|
my $HasAccess = $ConfigItemObject->Permission(
|
|
Scope => 'Class',
|
|
ClassID => $ClassID,
|
|
UserID => $Self->{UserID},
|
|
Type => $Self->{Config}->{Permission},
|
|
);
|
|
|
|
next CLASSID if !$HasAccess;
|
|
|
|
# Insert this class to be passed as search parameter for filter 'All'.
|
|
push @{$AccessClassList}, $ClassID;
|
|
|
|
# Increase the PrioCounter.
|
|
$PrioCounter++;
|
|
|
|
# Add filter with params for the search method.
|
|
$Filters{$ClassID} = {
|
|
Name => $ClassList->{$ClassID},
|
|
Prio => $PrioCounter,
|
|
Search => {
|
|
ClassIDs => [$ClassID],
|
|
DeplStateIDs => $DeplStateIDs,
|
|
OrderBy => \@SortByArray,
|
|
OrderByDirection => \@OrderByArray,
|
|
Limit => $Self->{SearchLimit},
|
|
},
|
|
};
|
|
|
|
# Remember the first class id to show this in the overview
|
|
# if no class id was given.
|
|
if ( !$ClassIDAuto ) {
|
|
$ClassIDAuto = $ClassID;
|
|
}
|
|
}
|
|
|
|
# If only one filter exists.
|
|
if ( scalar keys %Filters == 1 ) {
|
|
|
|
# Get the name of the only filter.
|
|
my ($FilterKey) = keys %Filters;
|
|
|
|
# Activate this filter.
|
|
$Self->{Filter} = $Filters{$FilterKey}->{Name};
|
|
}
|
|
else {
|
|
|
|
# Add default filter, which shows all items.
|
|
$Filters{All} = {
|
|
Name => 'All',
|
|
Prio => 1000,
|
|
Search => {
|
|
ClassIDs => $AccessClassList,
|
|
DeplStateIDs => $DeplStateIDs,
|
|
OrderBy => \@SortByArray,
|
|
OrderByDirection => \@OrderByArray,
|
|
Limit => $Self->{SearchLimit},
|
|
},
|
|
};
|
|
|
|
# If no filter was selected activate the filter for the default class.
|
|
if ( !$Self->{Filter} ) {
|
|
$Self->{Filter} = $ClassIDAuto;
|
|
}
|
|
}
|
|
|
|
# Get given filters.
|
|
my @NavBarFilters;
|
|
for my $Prio ( sort keys %Filters ) {
|
|
push @NavBarFilters, $Filters{$Prio};
|
|
}
|
|
|
|
# Sort according to prio.
|
|
@NavBarFilters = sort { $a->{Prio} <=> $b->{Prio} } @NavBarFilters;
|
|
|
|
# Find out which columns should be shown.
|
|
my @ShowColumns;
|
|
my @XMLShowColumns;
|
|
if ( $Self->{Config}->{DefaultColumns} ) {
|
|
|
|
# Get all possible columns from config.
|
|
my %PossibleColumn = %{ $Self->{Config}->{DefaultColumns} };
|
|
|
|
# Show column "Class" if filter 'All' is selected.
|
|
if ( $Self->{Filter} eq 'All' ) {
|
|
$PossibleColumn{Class} = '1';
|
|
}
|
|
|
|
# Get the column names that should be shown.
|
|
COLUMNNAME:
|
|
for my $Name ( sort keys %PossibleColumn ) {
|
|
next COLUMNNAME if !$PossibleColumn{$Name};
|
|
push @ShowColumns, $Name;
|
|
}
|
|
}
|
|
|
|
# Get frontend config.
|
|
my ($Module) = $Self->{Action} =~ m{^Agent(.*)}xms;
|
|
my $ShowColumnsByClassConfig
|
|
= $Kernel::OM->Get('Kernel::Config')->Get( 'Frontend::Agent::' . $Module . '::ITSMConfigItem' );
|
|
|
|
my $ShowColumnsByClass = $ShowColumnsByClassConfig->{ShowColumnsByClass} // '';
|
|
|
|
# Get the configured columns and reorganize them by class name.
|
|
if (
|
|
IsArrayRefWithData($ShowColumnsByClass)
|
|
&& $Self->{Filter}
|
|
&& $Self->{Filter} ne 'All'
|
|
)
|
|
{
|
|
|
|
my %ColumnByClass;
|
|
NAME:
|
|
for my $Name ( @{$ShowColumnsByClass} ) {
|
|
my ( $Class, $Column ) = split /::/, $Name, 2;
|
|
|
|
next NAME if !$Column;
|
|
|
|
push @{ $ColumnByClass{$Class} }, $Column;
|
|
}
|
|
|
|
# Check if there is a specific column config for the selected class.
|
|
if ( $ColumnByClass{ $Self->{Filter} } ) {
|
|
@ShowColumns = @{ $ColumnByClass{ $Self->{Filter} } };
|
|
}
|
|
}
|
|
|
|
if (@ShowColumns) {
|
|
|
|
for my $Column (@ShowColumns) {
|
|
|
|
# Create needed veriables.
|
|
my $CSS = 'OverviewHeader';
|
|
my $OrderBy;
|
|
|
|
# Remove ID if necesary.
|
|
if ( $Param{SortBy} ) {
|
|
$Param{SortBy} = ( $Param{SortBy} eq 'InciStateID' )
|
|
? 'CurInciState'
|
|
: ( $Param{SortBy} eq 'DeplStateID' ) ? 'CurDeplState'
|
|
: ( $Param{SortBy} eq 'ClassID' ) ? 'Class'
|
|
: ( $Param{SortBy} eq 'ChangeTime' ) ? 'LastChanged'
|
|
: $Param{SortBy};
|
|
}
|
|
|
|
# Set the correct Set CSS class and order by link.
|
|
if ( $Param{SortBy} && ( $Param{SortBy} eq $Column ) ) {
|
|
if ( $Param{OrderBy} && ( $Param{OrderBy} eq 'Up' ) ) {
|
|
$OrderBy = 'Down';
|
|
$CSS .= ' SortDescendingLarge';
|
|
}
|
|
else {
|
|
$OrderBy = 'Up';
|
|
$CSS .= ' SortAscendingLarge';
|
|
}
|
|
}
|
|
else {
|
|
$OrderBy = 'Up';
|
|
}
|
|
|
|
# Set column.
|
|
$Param{Column} = $Column;
|
|
|
|
# Create header block.
|
|
$LayoutObject->Block(
|
|
Name => 'Record' . $Column . 'Header',
|
|
Data => {
|
|
%Param,
|
|
CSS => $CSS,
|
|
OrderBy => $OrderBy,
|
|
},
|
|
);
|
|
}
|
|
}
|
|
|
|
# Get assigned config items (to customer or customer user).
|
|
my $AssignedCIs = $Self->_AssignedCIsGet(
|
|
Filter => $Self->{Filter},
|
|
);
|
|
my @AssignedConfigItemIDs = @{ $AssignedCIs->{ConfigItemIDs} };
|
|
|
|
# Get all assigned config items for count.
|
|
my $CountCIs = $Self->_AssignedCIsGet(
|
|
Filter => 'All',
|
|
Count => 1,
|
|
);
|
|
|
|
# Create search with sorting parameters.
|
|
my $AssignedConfigItemIDs;
|
|
if ( IsArrayRefWithData( \@AssignedConfigItemIDs ) ) {
|
|
$AssignedConfigItemIDs = $ConfigItemObject->ConfigItemSearch(
|
|
ConfigItemIDs => \@AssignedConfigItemIDs,
|
|
OrderBy => \@SortByArray,
|
|
OrderByDirection => \@OrderByArray,
|
|
);
|
|
}
|
|
|
|
# Clear old array and push new data.
|
|
if ( IsArrayRefWithData($AssignedConfigItemIDs) ) {
|
|
|
|
@AssignedConfigItemIDs = ();
|
|
push @AssignedConfigItemIDs, @{$AssignedConfigItemIDs};
|
|
}
|
|
|
|
if (@ShowColumns) {
|
|
|
|
# Get the XML column headers only if the filter is not set to 'all'
|
|
# and if there are CIs to show.
|
|
if ( $Self->{Filter} && $Self->{Filter} ne 'All' && @AssignedConfigItemIDs ) {
|
|
|
|
# Get the version data of the first config item, including all the XML data
|
|
# to get the column header names.
|
|
my $ConfigItem = $ConfigItemObject->VersionGet(
|
|
ConfigItemID => $AssignedConfigItemIDs[0],
|
|
XMLDataGet => 1,
|
|
);
|
|
|
|
# Convert the XML data into a hash.
|
|
my $ExtendedVersionData = $LayoutObject->XMLData2Hash(
|
|
XMLDefinition => $ConfigItem->{XMLDefinition},
|
|
XMLData => $ConfigItem->{XMLData}->[1]->{Version}->[1],
|
|
Attributes => \@ShowColumns,
|
|
);
|
|
|
|
# Get the xml columns (they contain ::).
|
|
@XMLShowColumns = grep {/::/} @ShowColumns;
|
|
|
|
COLUMN:
|
|
for my $Column (@XMLShowColumns) {
|
|
|
|
# Check if column exists in CI-Data.
|
|
next COLUMN if !$ExtendedVersionData->{$Column}->{Name};
|
|
|
|
# Show the xml attribute header.
|
|
$LayoutObject->Block(
|
|
Name => 'RecordXMLAttributeHeader',
|
|
Data => {
|
|
%Param,
|
|
XMLAttributeHeader => $ExtendedVersionData->{$Column}->{Name},
|
|
},
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
# Build filter content.
|
|
$LayoutObject->Block(
|
|
Name => 'OverviewNavBarFilter',
|
|
Data => {
|
|
%Filters,
|
|
},
|
|
);
|
|
|
|
# Set summary for page nav.
|
|
my %Summary;
|
|
|
|
# Loop over filters.
|
|
my $Count = 0;
|
|
FILTER:
|
|
for my $Filter (@NavBarFilters) {
|
|
|
|
# Get count by assigned config item ids.
|
|
$Filter->{Count} = $CountCIs->{ $Filter->{Name} } // '0';
|
|
|
|
$Count++;
|
|
if ( $Count == scalar @NavBarFilters ) {
|
|
$Filter->{CSS} = 'Last';
|
|
}
|
|
$LayoutObject->Block(
|
|
Name => 'OverviewNavBarFilterItem',
|
|
Data => {
|
|
%Param,
|
|
%{$Filter},
|
|
},
|
|
);
|
|
if ( $Filter->{Name} eq $Self->{Filter} ) {
|
|
$LayoutObject->Block(
|
|
Name => 'OverviewNavBarFilterItemSelected',
|
|
Data => {
|
|
%Param,
|
|
%{$Filter},
|
|
},
|
|
);
|
|
}
|
|
else {
|
|
$LayoutObject->Block(
|
|
Name => 'OverviewNavBarFilterItemSelectedNot',
|
|
Data => {
|
|
%Param,
|
|
%{$Filter},
|
|
},
|
|
);
|
|
}
|
|
|
|
# Add filter to new hash.
|
|
$Summary{ $Filter->{Name} } = \%{$Filter};
|
|
}
|
|
|
|
# Add page nav bar.
|
|
my $Total = $Summary{ $Self->{Filter} }->{Count} || 0;
|
|
|
|
my $LinkPage =
|
|
'Subaction=Element;Name=' . $Self->{Name}
|
|
. ';Filter=' . $Self->{Filter}
|
|
. ';SortBy=' . ( $Param{SortBy} || '' )
|
|
. ';OrderBy=' . ( $Param{OrderBy} || '' )
|
|
. ';';
|
|
|
|
if ( $Param{CustomerID} ) {
|
|
$LinkPage .= 'CustomerID=' . $LayoutObject->LinkEncode( $Param{CustomerID} ) . ';';
|
|
}
|
|
if ( $Param{CustomerUserID} ) {
|
|
$LinkPage .= 'CustomerUserID=' . $LayoutObject->LinkEncode( $Param{CustomerUserID} ) . ';';
|
|
}
|
|
|
|
my %PageNav = $LayoutObject->PageNavBar(
|
|
StartHit => $Self->{StartHit},
|
|
PageShown => $Self->{PageShown},
|
|
AllHits => $Total || 1,
|
|
Action => 'Action=' . $LayoutObject->{Action},
|
|
Link => $LinkPage,
|
|
AJAXReplace => 'Dashboard' . $Self->{Name},
|
|
IDPrefix => 'Dashboard' . $Self->{Name},
|
|
AJAX => $Param{AJAX},
|
|
);
|
|
|
|
$LayoutObject->Block(
|
|
Name => 'ContentLargeITSMConfigItemGenericFilterNavBar',
|
|
Data => {
|
|
%{ $Self->{Config} },
|
|
Name => $Self->{Name},
|
|
%PageNav,
|
|
},
|
|
);
|
|
|
|
# Show config items if there are some.
|
|
my $Counter = 0;
|
|
if (@AssignedConfigItemIDs) {
|
|
|
|
# To store all data.
|
|
my %Data;
|
|
|
|
CONFIGITEMID:
|
|
for my $ConfigItemID (@AssignedConfigItemIDs) {
|
|
$Counter++;
|
|
if (
|
|
$Counter >= $Self->{StartHit}
|
|
&& $Counter < ( $Self->{PageShown} + $Self->{StartHit} )
|
|
)
|
|
{
|
|
|
|
# Get config item data.
|
|
my $ConfigItem = $ConfigItemObject->VersionGet(
|
|
ConfigItemID => $ConfigItemID,
|
|
XMLDataGet => 1,
|
|
);
|
|
|
|
next CONFIGITEMID if !$ConfigItem;
|
|
|
|
# Convert the XML data into a hash.
|
|
my $ExtendedVersionData = $LayoutObject->XMLData2Hash(
|
|
XMLDefinition => $ConfigItem->{XMLDefinition},
|
|
XMLData => $ConfigItem->{XMLData}->[1]->{Version}->[1],
|
|
Attributes => \@ShowColumns,
|
|
);
|
|
|
|
# Store config item data.
|
|
%Data = %{$ConfigItem};
|
|
|
|
# Build record block.
|
|
$LayoutObject->Block(
|
|
Name => 'Record',
|
|
Data => {
|
|
%Param,
|
|
%Data,
|
|
},
|
|
);
|
|
|
|
# Build column record blocks.
|
|
if (@ShowColumns) {
|
|
|
|
COLUMN:
|
|
for my $Column (@ShowColumns) {
|
|
$LayoutObject->Block(
|
|
Name => 'Record' . $Column,
|
|
Data => {
|
|
%Param,
|
|
%Data,
|
|
CurInciSignal => $InciSignals{ $Data{CurInciStateType} },
|
|
CurDeplSignal => $DeplSignals{ $Data{CurDeplState} },
|
|
},
|
|
);
|
|
|
|
# Show links if available.
|
|
$LayoutObject->Block(
|
|
Name => 'Record' . $Column . 'LinkStart',
|
|
Data => {
|
|
%Param,
|
|
%Data,
|
|
},
|
|
);
|
|
$LayoutObject->Block(
|
|
Name => 'Record' . $Column . 'LinkEnd',
|
|
Data => {
|
|
%Param,
|
|
%Data,
|
|
},
|
|
);
|
|
}
|
|
|
|
COLUMN:
|
|
for my $Column (@XMLShowColumns) {
|
|
|
|
# Check if column exists in CI-Data.
|
|
next COLUMN if !$ExtendedVersionData->{$Column}->{Name};
|
|
|
|
# Convert to ascii text in case the value contains html.
|
|
my $Value = $Kernel::OM->Get('Kernel::System::HTMLUtils')
|
|
->ToAscii( String => $ExtendedVersionData->{$Column}->{Value} // '' )
|
|
// '';
|
|
|
|
# Convert all whitespace and newlines to single spaces.
|
|
$Value =~ s{ \s+ }{ }gxms;
|
|
|
|
# Show the xml attribute data.
|
|
$LayoutObject->Block(
|
|
Name => 'RecordXMLAttribute',
|
|
Data => {
|
|
%Param,
|
|
XMLAttributeData => $Value,
|
|
},
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
# If there are no config items to show, a no data found message is displayed in the table.
|
|
else {
|
|
$LayoutObject->Block(
|
|
Name => 'NoDataFoundMsg',
|
|
Data => {
|
|
TotalColumns => scalar @ShowColumns,
|
|
},
|
|
);
|
|
}
|
|
|
|
my $NameHTML = $Self->{Name};
|
|
$NameHTML =~ s{-}{_}xmsg;
|
|
|
|
# Send data to JS.
|
|
$LayoutObject->AddJSData(
|
|
Key => 'ITSMConfigItemGeneric',
|
|
Value => {
|
|
Name => $Self->{Name},
|
|
NameHTML => $NameHTML,
|
|
},
|
|
);
|
|
|
|
my $Content = $LayoutObject->Output(
|
|
TemplateFile => 'AgentDashboardITSMConfigItemGeneric',
|
|
Data => {
|
|
%{ $Self->{Config} },
|
|
Name => $Self->{Name},
|
|
StyleClasses => $StyleClasses,
|
|
},
|
|
AJAX => $Param{AJAX},
|
|
);
|
|
|
|
return $Content;
|
|
}
|
|
|
|
sub _AssignedCIsGet {
|
|
my ( $Self, %Param ) = @_;
|
|
|
|
# Define cache key.
|
|
my $CacheKey;
|
|
if ( $Self->{CustomerID} ) {
|
|
$CacheKey = 'AssignedCIs-' . $Param{Filter} . '-' . $Self->{CustomerID};
|
|
}
|
|
elsif ( $Self->{CustomerUserID} ) {
|
|
$CacheKey = 'AssignedCIs-' . $Param{Filter} . '-' . $Self->{CustomerUserID};
|
|
}
|
|
else {
|
|
$CacheKey = 'AssignedCIs-' . $Param{Filter} . '-' . $Self->{UserID};
|
|
}
|
|
|
|
my $Content = $Kernel::OM->Get('Kernel::System::Cache')->Get(
|
|
Type => 'DashboardITSMConfigItemGeneric',
|
|
Key => $CacheKey,
|
|
);
|
|
return $Content if defined $Content && $Param{Count};
|
|
|
|
# Get the defined param.
|
|
my @Params = split /;/, $Self->{Config}->{Attributes};
|
|
|
|
# Define result.
|
|
my @ConfigItemIDs;
|
|
my %Result;
|
|
|
|
# Get key for CI search.
|
|
my $ConfigItemKey = $Self->{Config}->{ConfigItemKey} // '';
|
|
|
|
return if !$ConfigItemKey;
|
|
|
|
# Get config item object.
|
|
my $ConfigItemObject = $Kernel::OM->Get('Kernel::System::ITSMConfigItem');
|
|
|
|
STRING:
|
|
for my $String (@Params) {
|
|
next STRING if !$String;
|
|
my ( $Key, $Value ) = split /=/, $String;
|
|
|
|
if ( $Key eq 'CustomerCompany' ) {
|
|
|
|
CLASS:
|
|
for my $Class ( sort keys %{$ConfigItemKey} ) {
|
|
|
|
# Skip other classes if filter is set.
|
|
next CLASS if $Param{Filter} && ( $Param{Filter} ne $Class && $Param{Filter} ne 'All' );
|
|
|
|
my $ClassID = $Self->_ClassIDByNameGet(
|
|
Value => $Class,
|
|
);
|
|
|
|
# Skip if we have no class id.
|
|
next CLASS if !$ClassID;
|
|
|
|
my @SearchKey = (
|
|
{
|
|
"[1]{'Version'}[1]{'$ConfigItemKey->{$Class}'}[%]{'Content'}" => $Self->{CustomerID},
|
|
}
|
|
);
|
|
|
|
# Perform config item search (extended).
|
|
my $ConfigItemIDs = $ConfigItemObject->ConfigItemSearchExtended(
|
|
ClassIDs => [$ClassID],
|
|
What => \@SearchKey,
|
|
);
|
|
|
|
next CLASS if !IsArrayRefWithData($ConfigItemIDs);
|
|
|
|
push @ConfigItemIDs, @{$ConfigItemIDs};
|
|
|
|
# Count config items per class.
|
|
if ( $Param{Count} ) {
|
|
$Result{$Class} = scalar @{$ConfigItemIDs};
|
|
}
|
|
}
|
|
}
|
|
elsif ( $Key eq 'Customer' ) {
|
|
|
|
CLASS:
|
|
for my $Class ( sort keys %{$ConfigItemKey} ) {
|
|
|
|
# Skip other classes if filter is set.
|
|
next CLASS if $Param{Filter} && ( $Param{Filter} ne $Class && $Param{Filter} ne 'All' );
|
|
|
|
my $ClassID = $Self->_ClassIDByNameGet(
|
|
Value => $Class,
|
|
);
|
|
|
|
# Skip if we have no class id.
|
|
next CLASS if !$ClassID;
|
|
|
|
my @SearchKey = (
|
|
{
|
|
"[1]{'Version'}[1]{'$ConfigItemKey->{$Class}'}[%]{'Content'}" => $Self->{CustomerUserID},
|
|
}
|
|
);
|
|
|
|
# Perform config item search (extended).
|
|
my $ConfigItemIDs = $ConfigItemObject->ConfigItemSearchExtended(
|
|
ClassIDs => [$ClassID],
|
|
What => \@SearchKey,
|
|
);
|
|
|
|
next CLASS if !IsArrayRefWithData($ConfigItemIDs);
|
|
|
|
push @ConfigItemIDs, @{$ConfigItemIDs};
|
|
|
|
# Count config items per class.
|
|
if ( $Param{Count} ) {
|
|
$Result{$Class} = scalar @{$ConfigItemIDs};
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
|
|
$Kernel::OM->Get('Kernel::System::Log')->Log(
|
|
Priority => 'error',
|
|
Message => 'Need CustomerCompany or Customer as attribute.',
|
|
);
|
|
return;
|
|
}
|
|
}
|
|
|
|
# Remove duplicated config item ids.
|
|
my %TempConfigItemIDs = map { $_ => 1 } @ConfigItemIDs;
|
|
@ConfigItemIDs = sort keys %TempConfigItemIDs;
|
|
|
|
$Result{ConfigItemIDs} = \@ConfigItemIDs;
|
|
|
|
# Add count for all items.
|
|
if ( $Param{Count} ) {
|
|
$Result{All} = scalar @ConfigItemIDs;
|
|
}
|
|
|
|
if ( $Self->{Config}->{CacheTTLLocal} && $Param{Count} ) {
|
|
$Kernel::OM->Get('Kernel::System::Cache')->Set(
|
|
Type => 'DashboardITSMConfigItemGeneric',
|
|
Key => $CacheKey,
|
|
Value => \%Result,
|
|
TTL => 2 * 60,
|
|
);
|
|
}
|
|
|
|
return \%Result;
|
|
}
|
|
|
|
sub _ClassIDByNameGet {
|
|
my ( $Self, %Param ) = @_;
|
|
|
|
# Check needed stuff.
|
|
if ( !$Param{Value} ) {
|
|
$Kernel::OM->Get('Kernel::System::Log')->Log(
|
|
Priority => 'error',
|
|
Message => "Need class name!",
|
|
);
|
|
return;
|
|
}
|
|
|
|
# Get general catalog object.
|
|
my $GeneralCatalogObject = $Kernel::OM->Get('Kernel::System::GeneralCatalog');
|
|
|
|
# Get class list.
|
|
my $ClassList = $GeneralCatalogObject->ItemList(
|
|
Class => 'ITSM::ConfigItem::Class',
|
|
);
|
|
|
|
# Reverse class list.
|
|
my %ClassName2ID = reverse %{$ClassList};
|
|
|
|
# Get class id.
|
|
my $ClassID = $ClassName2ID{ $Param{Value} };
|
|
|
|
return if !$ClassID;
|
|
|
|
#Initiate permission check.
|
|
my $ConfigItemObject = $Kernel::OM->Get('Kernel::System::ITSMConfigItem');
|
|
|
|
my $HasAccess = $ConfigItemObject->Permission(
|
|
Scope => 'Class',
|
|
ClassID => $ClassID,
|
|
UserID => $Self->{UserID},
|
|
Type => $Self->{Config}->{Permission},
|
|
);
|
|
return if !$HasAccess;
|
|
|
|
# Return class id.
|
|
return $ClassID;
|
|
}
|
|
|
|
1;
|