558 lines
17 KiB
Perl
558 lines
17 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::AgentITSMConfigItemZoom;
|
|
|
|
use strict;
|
|
use warnings;
|
|
|
|
## nofilter(TidyAll::Plugin::OTRS::Migrations::OTRS6::SysConfig)
|
|
|
|
use Kernel::Language qw(Translatable);
|
|
|
|
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 ) = @_;
|
|
|
|
# get param object
|
|
my $ParamObject = $Kernel::OM->Get('Kernel::System::Web::Request');
|
|
|
|
# get params
|
|
my $ConfigItemID = $ParamObject->GetParam( Param => 'ConfigItemID' ) || 0;
|
|
my $VersionID = $ParamObject->GetParam( Param => 'VersionID' ) || 0;
|
|
|
|
# get layout object
|
|
my $LayoutObject = $Kernel::OM->Get('Kernel::Output::HTML::Layout');
|
|
|
|
# check needed stuff
|
|
if ( !$ConfigItemID ) {
|
|
return $LayoutObject->ErrorScreen(
|
|
Message => Translatable('No ConfigItemID is given!'),
|
|
Comment => Translatable('Please contact the administrator.'),
|
|
);
|
|
}
|
|
|
|
# get needed object
|
|
my $ConfigItemObject = $Kernel::OM->Get('Kernel::System::ITSMConfigItem');
|
|
my $ConfigObject = $Kernel::OM->Get('Kernel::Config');
|
|
|
|
# check for access rights
|
|
my $HasAccess = $ConfigItemObject->Permission(
|
|
Scope => 'Item',
|
|
ItemID => $ConfigItemID,
|
|
UserID => $Self->{UserID},
|
|
Type => $ConfigObject->Get("ITSMConfigItem::Frontend::$Self->{Action}")->{Permission},
|
|
);
|
|
|
|
if ( !$HasAccess ) {
|
|
|
|
# error page
|
|
return $LayoutObject->ErrorScreen(
|
|
Message => Translatable('Can\'t show item, no access rights for ConfigItem are given!'),
|
|
Comment => Translatable('Please contact the administrator.'),
|
|
);
|
|
}
|
|
|
|
# set show versions
|
|
$Param{ShowVersions} = 0;
|
|
if ( $ParamObject->GetParam( Param => 'ShowVersions' ) ) {
|
|
$Param{ShowVersions} = 1;
|
|
}
|
|
|
|
# get content
|
|
my $ConfigItem = $ConfigItemObject->ConfigItemGet(
|
|
ConfigItemID => $ConfigItemID,
|
|
);
|
|
if ( !$ConfigItem->{ConfigItemID} ) {
|
|
return $LayoutObject->ErrorScreen(
|
|
Message =>
|
|
$LayoutObject->{LanguageObject}->Translate( 'ConfigItemID %s not found in database!', $ConfigItemID ),
|
|
Comment => Translatable('Please contact the administrator.'),
|
|
);
|
|
}
|
|
|
|
# get version list
|
|
my $VersionList = $ConfigItemObject->VersionZoomList(
|
|
ConfigItemID => $ConfigItemID,
|
|
);
|
|
if ( !$VersionList->[0]->{VersionID} ) {
|
|
return $LayoutObject->ErrorScreen(
|
|
Message =>
|
|
$LayoutObject->{LanguageObject}->Translate( 'No version found for ConfigItemID %s!', $ConfigItemID ),
|
|
Comment => Translatable('Please contact the administrator.'),
|
|
);
|
|
}
|
|
|
|
# set version id
|
|
if ( !$VersionID ) {
|
|
$VersionID = $VersionList->[-1]->{VersionID};
|
|
}
|
|
if ( $VersionID ne $VersionList->[-1]->{VersionID} ) {
|
|
$Param{ShowVersions} = 1;
|
|
}
|
|
|
|
# set version id in param hash (only for menu module)
|
|
if ($VersionID) {
|
|
$Param{VersionID} = $VersionID;
|
|
}
|
|
|
|
# run config item menu modules
|
|
if ( ref $ConfigObject->Get('ITSMConfigItem::Frontend::MenuModule') eq 'HASH' ) {
|
|
my %Menus = %{ $ConfigObject->Get('ITSMConfigItem::Frontend::MenuModule') };
|
|
my $Counter = 0;
|
|
for my $Menu ( sort keys %Menus ) {
|
|
|
|
# load module
|
|
if ( $Kernel::OM->Get('Kernel::System::Main')->Require( $Menus{$Menu}->{Module} ) ) {
|
|
|
|
my $Object = $Menus{$Menu}->{Module}->new(
|
|
%{$Self},
|
|
ConfigItemID => $Self->{ConfigItemID},
|
|
);
|
|
|
|
# set classes
|
|
if ( $Menus{$Menu}->{Target} ) {
|
|
|
|
if ( $Menus{$Menu}->{Target} eq 'PopUp' ) {
|
|
$Menus{$Menu}->{MenuClass} = 'AsPopup';
|
|
}
|
|
elsif ( $Menus{$Menu}->{Target} eq 'Back' ) {
|
|
$Menus{$Menu}->{MenuClass} = 'HistoryBack';
|
|
}
|
|
|
|
}
|
|
|
|
# run module
|
|
$Counter = $Object->Run(
|
|
%Param,
|
|
ConfigItem => $ConfigItem,
|
|
Counter => $Counter,
|
|
Config => $Menus{$Menu},
|
|
MenuID => $Menu,
|
|
);
|
|
}
|
|
else {
|
|
return $LayoutObject->FatalError();
|
|
}
|
|
}
|
|
}
|
|
|
|
# build version tree
|
|
$LayoutObject->Block( Name => 'Tree' );
|
|
my $Counter = 1;
|
|
if ( !$Param{ShowVersions} && $VersionID eq $VersionList->[-1]->{VersionID} ) {
|
|
$Counter = @{$VersionList};
|
|
$VersionList = [ $VersionList->[-1] ];
|
|
}
|
|
|
|
# get last version
|
|
my $LastVersion = $VersionList->[-1];
|
|
|
|
# set incident signal
|
|
my %InciSignals = (
|
|
Translatable('operational') => 'greenled',
|
|
Translatable('warning') => 'yellowled',
|
|
Translatable('incident') => 'redled',
|
|
);
|
|
|
|
# to store the color for the deployment states
|
|
my %DeplSignals;
|
|
|
|
# get general catalog object
|
|
my $GeneralCatalogObject = $Kernel::OM->Get('Kernel::System::GeneralCatalog');
|
|
|
|
# get list of deployment states
|
|
my $DeploymentStatesList = $GeneralCatalogObject->ItemList(
|
|
Class => 'ITSM::ConfigItem::DeploymentState',
|
|
);
|
|
|
|
# set deployment style colors
|
|
my $StyleClasses = '';
|
|
|
|
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;
|
|
|
|
# covert to lower case
|
|
my $DeplStateColor = lc $Preferences{Color};
|
|
|
|
# add to style classes string
|
|
$StyleClasses .= "
|
|
.Flag span.$DeplState {
|
|
background-color: #$DeplStateColor;
|
|
}
|
|
";
|
|
}
|
|
|
|
# wrap into style tags
|
|
if ($StyleClasses) {
|
|
$StyleClasses = "<style>$StyleClasses</style>";
|
|
}
|
|
|
|
# output version tree header
|
|
if ( $Param{ShowVersions} ) {
|
|
$LayoutObject->Block(
|
|
Name => 'Collapse',
|
|
Data => {
|
|
ConfigItemID => $ConfigItemID,
|
|
},
|
|
);
|
|
}
|
|
else {
|
|
$LayoutObject->Block(
|
|
Name => 'Expand',
|
|
Data => {
|
|
ConfigItemID => $ConfigItemID,
|
|
},
|
|
);
|
|
}
|
|
|
|
# get user object
|
|
my $UserObject = $Kernel::OM->Get('Kernel::System::User');
|
|
|
|
# output version tree
|
|
for my $VersionHash ( @{$VersionList} ) {
|
|
|
|
$Param{CreateByUserFullName} = $UserObject->UserName(
|
|
UserID => $VersionHash->{CreateBy},
|
|
);
|
|
|
|
$LayoutObject->Block(
|
|
Name => 'TreeItem',
|
|
Data => {
|
|
%Param,
|
|
%{$ConfigItem},
|
|
%{$VersionHash},
|
|
Count => $Counter,
|
|
InciSignal => $InciSignals{ $VersionHash->{InciStateType} },
|
|
DeplSignal => $DeplSignals{ $VersionHash->{DeplState} },
|
|
Active => $VersionHash->{VersionID} eq $VersionID ? 'Active' : '',
|
|
},
|
|
);
|
|
|
|
$Counter++;
|
|
}
|
|
|
|
# output header
|
|
my $Output = $LayoutObject->Header( Value => $ConfigItem->{Number} );
|
|
$Output .= $LayoutObject->NavigationBar();
|
|
|
|
# get version
|
|
my $Version = $ConfigItemObject->VersionGet(
|
|
VersionID => $VersionID,
|
|
);
|
|
|
|
if (
|
|
$Version
|
|
&& ref $Version eq 'HASH'
|
|
&& $Version->{XMLDefinition}
|
|
&& $Version->{XMLData}
|
|
&& ref $Version->{XMLDefinition} eq 'ARRAY'
|
|
&& ref $Version->{XMLData} eq 'ARRAY'
|
|
&& $Version->{XMLData}->[1]
|
|
&& ref $Version->{XMLData}->[1] eq 'HASH'
|
|
&& $Version->{XMLData}->[1]->{Version}
|
|
&& ref $Version->{XMLData}->[1]->{Version} eq 'ARRAY'
|
|
)
|
|
{
|
|
|
|
# transform ascii to html
|
|
$Version->{Name} = $LayoutObject->Ascii2Html(
|
|
Text => $Version->{Name},
|
|
HTMLResultMode => 1,
|
|
LinkFeature => 1,
|
|
);
|
|
|
|
# output name
|
|
$LayoutObject->Block(
|
|
Name => 'Data',
|
|
Data => {
|
|
Name => Translatable('Name'),
|
|
Description => Translatable('The name of this config item'),
|
|
Value => $Version->{Name},
|
|
Identation => 10,
|
|
},
|
|
);
|
|
|
|
# output deployment state
|
|
$LayoutObject->Block(
|
|
Name => 'Data',
|
|
Data => {
|
|
Name => Translatable('Deployment State'),
|
|
Description => Translatable('The deployment state of this config item'),
|
|
Value => $LayoutObject->{LanguageObject}->Translate(
|
|
$Version->{DeplState},
|
|
),
|
|
Identation => 10,
|
|
},
|
|
);
|
|
|
|
# output incident state
|
|
$LayoutObject->Block(
|
|
Name => 'Data',
|
|
Data => {
|
|
Name => Translatable('Incident State'),
|
|
Description => Translatable('The incident state of this config item'),
|
|
Value => $LayoutObject->{LanguageObject}->Translate(
|
|
$Version->{InciState},
|
|
),
|
|
Identation => 10,
|
|
},
|
|
);
|
|
|
|
# start xml output
|
|
$Self->_XMLOutput(
|
|
XMLDefinition => $Version->{XMLDefinition},
|
|
XMLData => $Version->{XMLData}->[1]->{Version}->[1],
|
|
);
|
|
}
|
|
|
|
# get create & change user data
|
|
for my $Key (qw(Create Change)) {
|
|
$ConfigItem->{ $Key . 'ByUserFullName' } = $UserObject->UserName(
|
|
UserID => $ConfigItem->{ $Key . 'By' },
|
|
);
|
|
}
|
|
|
|
# output meta block
|
|
$LayoutObject->Block(
|
|
Name => 'Meta',
|
|
Data => {
|
|
%{$LastVersion},
|
|
%{$ConfigItem},
|
|
CurInciSignal => $InciSignals{ $LastVersion->{CurInciStateType} },
|
|
CurDeplSignal => $DeplSignals{ $LastVersion->{DeplState} },
|
|
},
|
|
);
|
|
|
|
# get linked objects
|
|
my $LinkListWithData = $Kernel::OM->Get('Kernel::System::LinkObject')->LinkListWithData(
|
|
Object => 'ITSMConfigItem',
|
|
Key => $ConfigItemID,
|
|
State => 'Valid',
|
|
UserID => $Self->{UserID},
|
|
);
|
|
|
|
# get link table view mode
|
|
my $LinkTableViewMode = $ConfigObject->Get('LinkObject::ViewMode');
|
|
|
|
# create the link table
|
|
my $LinkTableStrg = $LayoutObject->LinkObjectTableCreate(
|
|
LinkListWithData => $LinkListWithData,
|
|
ViewMode => $LinkTableViewMode,
|
|
Object => 'ITSMConfigItem',
|
|
Key => $ConfigItemID,
|
|
);
|
|
|
|
# output the link table
|
|
if ($LinkTableStrg) {
|
|
$LayoutObject->Block(
|
|
Name => 'LinkTable' . $LinkTableViewMode,
|
|
Data => {
|
|
LinkTableStrg => $LinkTableStrg,
|
|
},
|
|
);
|
|
}
|
|
|
|
my @Attachments = $ConfigItemObject->ConfigItemAttachmentList(
|
|
ConfigItemID => $ConfigItemID,
|
|
);
|
|
|
|
if (@Attachments) {
|
|
|
|
# get the metadata of the 1st attachment
|
|
my $FirstAttachment = $ConfigItemObject->ConfigItemAttachmentGet(
|
|
ConfigItemID => $ConfigItemID,
|
|
Filename => $Attachments[0],
|
|
);
|
|
|
|
$LayoutObject->Block(
|
|
Name => 'Attachments',
|
|
Data => {
|
|
ConfigItemID => $ConfigItemID,
|
|
Filename => $FirstAttachment->{Filename},
|
|
Filesize => $FirstAttachment->{Filesize},
|
|
},
|
|
);
|
|
|
|
# the 1st attachment was directly rendered into the 1st row's right cell, all further
|
|
# attachments are rendered into a separate row
|
|
ATTACHMENT:
|
|
for my $Attachment (@Attachments) {
|
|
|
|
# skip the 1st attachment
|
|
next ATTACHMENT if $Attachment eq $Attachments[0];
|
|
|
|
# get the metadata of the current attachment
|
|
my $AttachmentData = $ConfigItemObject->ConfigItemAttachmentGet(
|
|
ConfigItemID => $ConfigItemID,
|
|
Filename => $Attachment,
|
|
);
|
|
|
|
$LayoutObject->Block(
|
|
Name => 'AttachmentRow',
|
|
Data => {
|
|
ConfigItemID => $ConfigItemID,
|
|
Filename => $AttachmentData->{Filename},
|
|
Filesize => $AttachmentData->{Filesize},
|
|
},
|
|
);
|
|
}
|
|
}
|
|
|
|
# handle DownloadAttachment
|
|
if ( $Self->{Subaction} eq 'DownloadAttachment' ) {
|
|
|
|
# get data for attachment
|
|
my $Filename = $ParamObject->GetParam( Param => 'Filename' );
|
|
my $AttachmentData = $ConfigItemObject->ConfigItemAttachmentGet(
|
|
ConfigItemID => $ConfigItemID,
|
|
Filename => $Filename,
|
|
);
|
|
|
|
# return error if file does not exist
|
|
if ( !$AttachmentData ) {
|
|
$Kernel::OM->Get('Kernel::System::Log')->Log(
|
|
Message => "No such attachment ($Filename)!",
|
|
Priority => 'error',
|
|
);
|
|
return $LayoutObject->ErrorScreen();
|
|
}
|
|
|
|
return $LayoutObject->Attachment(
|
|
%{$AttachmentData},
|
|
Type => 'attachment',
|
|
);
|
|
}
|
|
|
|
# store last screen
|
|
$Kernel::OM->Get('Kernel::System::AuthSession')->UpdateSessionID(
|
|
SessionID => $Self->{SessionID},
|
|
Key => 'LastScreenView',
|
|
Value => $Self->{RequestedURL},
|
|
);
|
|
|
|
$LayoutObject->AddJSData(
|
|
Key => 'UserConfigItemZoomTableHeight',
|
|
Value => $Self->{UserConfigItemZoomTableHeight},
|
|
);
|
|
|
|
# start template output
|
|
$Output .= $LayoutObject->Output(
|
|
TemplateFile => 'AgentITSMConfigItemZoom',
|
|
Data => {
|
|
%{$LastVersion},
|
|
%{$ConfigItem},
|
|
CurInciSignal => $InciSignals{ $LastVersion->{CurInciStateType} },
|
|
CurDeplSignal => $DeplSignals{ $LastVersion->{DeplState} },
|
|
StyleClasses => $StyleClasses,
|
|
},
|
|
);
|
|
|
|
# add footer
|
|
$Output .= $LayoutObject->Footer();
|
|
|
|
return $Output;
|
|
}
|
|
|
|
sub _XMLOutput {
|
|
my ( $Self, %Param ) = @_;
|
|
|
|
# check needed stuff
|
|
return if !$Param{XMLData};
|
|
return if !$Param{XMLDefinition};
|
|
return if ref $Param{XMLData} ne 'HASH';
|
|
return if ref $Param{XMLDefinition} ne 'ARRAY';
|
|
|
|
$Param{Level} ||= 0;
|
|
|
|
ITEM:
|
|
for my $Item ( @{ $Param{XMLDefinition} } ) {
|
|
COUNTER:
|
|
for my $Counter ( 1 .. $Item->{CountMax} ) {
|
|
|
|
# stop loop, if no content was given
|
|
last COUNTER if !defined $Param{XMLData}->{ $Item->{Key} }->[$Counter]->{Content};
|
|
|
|
# lookup value
|
|
my $Value = $Kernel::OM->Get('Kernel::System::ITSMConfigItem')->XMLValueLookup(
|
|
Item => $Item,
|
|
Value => $Param{XMLData}->{ $Item->{Key} }->[$Counter]->{Content},
|
|
);
|
|
|
|
# get layout object
|
|
my $LayoutObject = $Kernel::OM->Get('Kernel::Output::HTML::Layout');
|
|
|
|
# create output string
|
|
$Value = $LayoutObject->ITSMConfigItemOutputStringCreate(
|
|
Value => $Value,
|
|
Item => $Item,
|
|
);
|
|
|
|
# calculate indentation for left-padding css based on 15px per level and 10px as default
|
|
my $Indentation = 10;
|
|
|
|
if ( $Param{Level} ) {
|
|
$Indentation += 15 * $Param{Level};
|
|
}
|
|
|
|
# output data block
|
|
$LayoutObject->Block(
|
|
Name => 'Data',
|
|
Data => {
|
|
Name => $Item->{Name},
|
|
Description => $Item->{Description} || $Item->{Name},
|
|
Value => $Value,
|
|
Indentation => $Indentation,
|
|
},
|
|
);
|
|
|
|
# start recursion, if "Sub" was found
|
|
if ( $Item->{Sub} ) {
|
|
$Self->_XMLOutput(
|
|
XMLDefinition => $Item->{Sub},
|
|
XMLData => $Param{XMLData}->{ $Item->{Key} }->[$Counter],
|
|
Level => $Param{Level} + 1,
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
1;
|