Commit e66ff1110e52fd0734b6354f23c7b6f24f99b5f8
0 parents
Exists in
master
First commit.
Showing
15 changed files
with
876 additions
and
0 deletions
Show diff stats
| 1 | +++ a/.project | |
| ... | ... | @@ -0,0 +1,17 @@ |
| 1 | +<?xml version="1.0" encoding="UTF-8"?> | |
| 2 | +<projectDescription> | |
| 3 | + <name>otrs-queues-panel</name> | |
| 4 | + <comment></comment> | |
| 5 | + <projects> | |
| 6 | + </projects> | |
| 7 | + <buildSpec> | |
| 8 | + <buildCommand> | |
| 9 | + <name>org.epic.perleditor.perlbuilder</name> | |
| 10 | + <arguments> | |
| 11 | + </arguments> | |
| 12 | + </buildCommand> | |
| 13 | + </buildSpec> | |
| 14 | + <natures> | |
| 15 | + <nature>org.epic.perleditor.perlnature</nature> | |
| 16 | + </natures> | |
| 17 | +</projectDescription> | ... | ... |
| 1 | +++ a/Kernel/Config/Files/QueuesPanel.xml | |
| ... | ... | @@ -0,0 +1,81 @@ |
| 1 | +<?xml version="1.0" encoding="UTF-8" ?> | |
| 2 | +<otrs_config init="Application" version="1.0"> | |
| 3 | + <ConfigItem Name="CustomerFrontend::Module###QueuesPanel" Required="0" Valid="1"> | |
| 4 | + <Description>FrontendModuleRegistration for QueuesPanel module.</Description> | |
| 5 | + <Group>Ticket</Group> | |
| 6 | + <SubGroup>Frontend::Customer::ModuleRegistration</SubGroup> | |
| 7 | + <Setting> | |
| 8 | + <FrontendModuleReg> | |
| 9 | + <Description>Module for choosing main queues to open tickets</Description> | |
| 10 | + <NavBarName>QueuesPanel</NavBarName> | |
| 11 | + <NavBar> | |
| 12 | + <Description>Queues panel</Description> | |
| 13 | + <Name>Queues panel</Name> | |
| 14 | + <Link>Action=QueuesPanel</Link> | |
| 15 | + <NavBar>QueuesPanel</NavBar> | |
| 16 | + <Type>Menu</Type> | |
| 17 | + <Prio>8400</Prio> | |
| 18 | + </NavBar> | |
| 19 | + | |
| 20 | + <!-- JQueryPlugin for colums --> | |
| 21 | + <Loader> | |
| 22 | + <JavaScript>thirdparty/hColumns/jquery.hcolumns.min.js</JavaScript> | |
| 23 | + <CSS>QueuesPanel.css</CSS> | |
| 24 | + <CSS>hColumns/hcolumns.css</CSS> | |
| 25 | + <CSS>hColumns/hcolumns-intro.css</CSS> | |
| 26 | + <CSS>hColumns/reset.css</CSS> | |
| 27 | + </Loader> | |
| 28 | + </FrontendModuleReg> | |
| 29 | + </Setting> | |
| 30 | + </ConfigItem> | |
| 31 | + | |
| 32 | + <ConfigItem Name="PublicFrontend::Module###QueuesPanelPublic" Required="0" Valid="1"> | |
| 33 | + <Description>FrontendModuleRegistration for QueuesPanelPublic module.</Description> | |
| 34 | + <Group>Framework</Group> | |
| 35 | + <SubGroup>Frontend::Public::ModuleRegistration</SubGroup> | |
| 36 | + <Setting> | |
| 37 | + <FrontendModuleReg> | |
| 38 | + <Description>Module for choosing main queues to open tickets</Description> | |
| 39 | + <NavBarName>QueuesPanel</NavBarName> | |
| 40 | + <NavBar> | |
| 41 | + <Description>Queues panel</Description> | |
| 42 | + <Name>Queues panel</Name> | |
| 43 | + <Link>Action=QueuesPanelPublic</Link> | |
| 44 | + <NavBar>QueuesPanel</NavBar> | |
| 45 | + <Type>Menu</Type> | |
| 46 | + <Prio>8400</Prio> | |
| 47 | + </NavBar> | |
| 48 | + <!-- JQueryPlugin for colums --> | |
| 49 | + <Loader> | |
| 50 | + <JavaScript>thirdparty/hColumns/jquery.hcolumns.min.js</JavaScript> | |
| 51 | + <CSS>QueuesPanel.css</CSS> | |
| 52 | + <CSS>hColumns/hcolumns.css</CSS> | |
| 53 | + <CSS>hColumns/hcolumns-intro.css</CSS> | |
| 54 | + <CSS>hColumns/reset.css</CSS> | |
| 55 | + </Loader> | |
| 56 | + </FrontendModuleReg> | |
| 57 | + </Setting> | |
| 58 | + </ConfigItem> | |
| 59 | + | |
| 60 | + | |
| 61 | + <ConfigItem Name="Ticket::Frontend::Customer::QueuesPanel###MessageChooseQueuePublic" | |
| 62 | + Required="0" Valid="1"> | |
| 63 | + <Description>Message to let the user choose a queue.</Description> | |
| 64 | + <Group>Ticket</Group> | |
| 65 | + <SubGroup>Frontend::Customer::QueuesPanel</SubGroup> | |
| 66 | + <Setting> | |
| 67 | + <String Regex="">Escolha o local para o qual deseja atendimento</String> | |
| 68 | + </Setting> | |
| 69 | + </ConfigItem> | |
| 70 | + | |
| 71 | + <ConfigItem Name="Ticket::Frontend::Customer::QueuesPanel###MessageChooseQueue" | |
| 72 | + Required="0" Valid="1"> | |
| 73 | + <Description>Message to let the user choose a queue.</Description> | |
| 74 | + <Group>Ticket</Group> | |
| 75 | + <SubGroup>Frontend::Customer::QueuesPanel</SubGroup> | |
| 76 | + <Setting> | |
| 77 | + <String Regex="">Escolha o local para o qual deseja atendimento</String> | |
| 78 | + </Setting> | |
| 79 | + </ConfigItem> | |
| 80 | + | |
| 81 | +</otrs_config> | |
| 0 | 82 | \ No newline at end of file | ... | ... |
| 1 | +++ a/Kernel/Language/pt_BR_QueuesPanel.pm | |
| ... | ... | @@ -0,0 +1,26 @@ |
| 1 | +# Kernel/Modules/pt_BR_QueuesPanel.pm - translations for QueuesPanel | |
| 2 | +# | |
| 3 | +# Copyright (C) 2014 SeTIC - UFSC - http://setic.ufsc.br/ | |
| 4 | +# Version 01/08/2015 - Adjustments for OTRS 4 | |
| 5 | +# | |
| 6 | +# -- | |
| 7 | +# This software comes with ABSOLUTELY NO WARRANTY. For details, see | |
| 8 | +# the enclosed file COPYING for license information (AGPL). If you | |
| 9 | +# did not receive this file, see http://www.gnu.org/licenses/agpl.txt. | |
| 10 | +# -- | |
| 11 | +package Kernel::Language::pt_BR_NewTicketWizard; | |
| 12 | + | |
| 13 | +use strict; | |
| 14 | +use warnings; | |
| 15 | +use utf8; | |
| 16 | + | |
| 17 | +sub Data { | |
| 18 | + my $Self = shift; | |
| 19 | + | |
| 20 | + $Self->{Translation}->{'The following maintenances are in progress'} = 'As seguintes manutenções estão ocorrendo'; | |
| 21 | + $Self->{Translation}->{'Started at: '} = 'Iniciada em:'; | |
| 22 | + $Self->{Translation}->{'Queues panel'} = 'Novo chamado'; | |
| 23 | + $Self->{Translation}->{'Choose the service to ask for support'} = 'Escolha o serviço para o qual deseja suporte'; | |
| 24 | + return 1; | |
| 25 | +} | |
| 26 | +1; | |
| 0 | 27 | \ No newline at end of file | ... | ... |
| 1 | +++ a/Kernel/Language/pt_BR_QueuesPanelPublic.pm | |
| ... | ... | @@ -0,0 +1,27 @@ |
| 1 | +# Kernel/Modules/pt_BR_QueuesPanelPublic.pm - translations for QueuesPanelPublic | |
| 2 | +# | |
| 3 | +# Copyright (C) 2014 SeTIC - UFSC - http://setic.ufsc.br/ | |
| 4 | +# Version 01/08/2015 - Adjustments for OTRS 4 | |
| 5 | +# | |
| 6 | +# -- | |
| 7 | +# -- | |
| 8 | +# This software comes with ABSOLUTELY NO WARRANTY. For details, see | |
| 9 | +# the enclosed file COPYING for license information (AGPL). If you | |
| 10 | +# did not receive this file, see http://www.gnu.org/licenses/agpl.txt. | |
| 11 | +# -- | |
| 12 | +package Kernel::Language::pt_BR_NewTicketWizard; | |
| 13 | + | |
| 14 | +use strict; | |
| 15 | +use warnings; | |
| 16 | +use utf8; | |
| 17 | + | |
| 18 | +sub Data { | |
| 19 | + my $Self = shift; | |
| 20 | + | |
| 21 | + $Self->{Translation}->{'The following maintenances are in progress'} = 'As seguintes manutenções estão ocorrendo'; | |
| 22 | + $Self->{Translation}->{'Started at: '} = 'Iniciada em:'; | |
| 23 | + $Self->{Translation}->{'Queues panel'} = 'Novo chamado'; | |
| 24 | + $Self->{Translation}->{'Choose the service to ask for support'} = 'Escolha o serviço para o qual deseja suporte'; | |
| 25 | + return 1; | |
| 26 | +} | |
| 27 | +1; | |
| 0 | 28 | \ No newline at end of file | ... | ... |
| 1 | +++ a/Kernel/Modules/QueuesPanel.pm | |
| ... | ... | @@ -0,0 +1,185 @@ |
| 1 | +# -- | |
| 2 | +# Kernel/Modules/QueuesPanel.pm - frontend module for choosing top queues | |
| 3 | +# | |
| 4 | +# Copyright (C) SeTIC - UFSC - http://setic.ufsc.br/ | |
| 5 | +# Version 01/08/2015 - Support for OTRS 4.0.3 | |
| 6 | +# | |
| 7 | +# -- | |
| 8 | +# This software comes with ABSOLUTELY NO WARRANTY. For details, see | |
| 9 | +# the enclosed file COPYING for license information (AGPL). If you | |
| 10 | +# did not receive this file, see http://www.gnu.org/licenses/agpl.txt. | |
| 11 | +# -- | |
| 12 | +package Kernel::Modules::QueuesPanel; | |
| 13 | + | |
| 14 | +use strict; | |
| 15 | +use warnings; | |
| 16 | + | |
| 17 | +use Kernel::System::VariableCheck qw(:all); | |
| 18 | + | |
| 19 | +our @ObjectDependencies = ( | |
| 20 | +"Kernel::System::Web::Request", | |
| 21 | +"Kernel::System::DB", | |
| 22 | +"Kernel::Output::HTML::Layout", | |
| 23 | +"KerneL::System::Log", | |
| 24 | +"Kernel::Config", | |
| 25 | +"Kernel::System::Queue"); | |
| 26 | + | |
| 27 | +sub new { | |
| 28 | + my ( $Type, %Param ) = @_; | |
| 29 | + | |
| 30 | + # allocate new hash for object | |
| 31 | + my $Self = {%Param}; | |
| 32 | + bless( $Self, $Type ); | |
| 33 | + | |
| 34 | + return $Self; | |
| 35 | +} | |
| 36 | + | |
| 37 | +sub Run { | |
| 38 | + my ( $Self, %Param ) = @_; | |
| 39 | + my %Data = (); | |
| 40 | + | |
| 41 | + my $ConfigObject = $Kernel::OM->Get("Kernel::Config"); | |
| 42 | + my $LayoutObject = $Kernel::OM->Get("Kernel::Output::HTML::Layout"); | |
| 43 | + | |
| 44 | + $Self->{UrlAtendimento} = '/otrs/customer.pl?Action=NewTicketWizard;QueueID='; | |
| 45 | + | |
| 46 | + $Data{"QueueJS"} = $Self->BuildQueuesJS(); | |
| 47 | + | |
| 48 | + $Self->{Config} = $ConfigObject->Get("Ticket::Frontend::Customer::QueuesPanel"); | |
| 49 | + my $msgChooseService = $Self->{Config}->{"MessageChooseQueue"}; | |
| 50 | + $Data{MsgChooseQueue} = $msgChooseService; | |
| 51 | + | |
| 52 | + # build output | |
| 53 | + my $Output = $LayoutObject->CustomerHeader( Title => $LayoutObject->{LanguageObject}->Translate("Queues panel") ); | |
| 54 | + | |
| 55 | + $Output .= $LayoutObject->Output( | |
| 56 | + Data => \%Data, | |
| 57 | + TemplateFile => 'QueuesPanel', | |
| 58 | + ); | |
| 59 | + $Output .= $LayoutObject->CustomerFooter(); | |
| 60 | + return $Output; | |
| 61 | +} | |
| 62 | + | |
| 63 | +sub BuildQueuesJS { | |
| 64 | + my ( $Self, %Param ) = @_; | |
| 65 | + | |
| 66 | + # Get queues | |
| 67 | + my %Queues = (); | |
| 68 | + | |
| 69 | + my $DBObject = $Kernel::OM->Get("Kernel::System::DB"); | |
| 70 | + | |
| 71 | + $DBObject->Prepare( SQL => "SELECT id, name FROM queue WHERE valid_id = 1 ORDER BY name ASC", ); | |
| 72 | + while ( my @Row = $DBObject->FetchrowArray() ) { | |
| 73 | + $Queues{ $Row[0] } = $Row[1]; | |
| 74 | + } | |
| 75 | + | |
| 76 | + my $result = | |
| 77 | + '$(document).ready(function() {' . "\n\t" | |
| 78 | + . ' $("#columns").hColumns({' | |
| 79 | + . "\n\t\t" | |
| 80 | + . ' nodeSource: function(node_id, callback) {' . "\n"; | |
| 81 | + | |
| 82 | + for my $queue ( keys %Queues ) { | |
| 83 | + $result = $result . $Self->BuildQueueJS( Queues => \%Queues, Queue => $Queues{$queue}, QueueID => $queue ); | |
| 84 | + } | |
| 85 | + | |
| 86 | + $result = $result . $Self->BuildTopQueuesJS( Queues => \%Queues ); | |
| 87 | + | |
| 88 | + $result = $result . "\n\t}});\n});"; | |
| 89 | + | |
| 90 | + return $result; | |
| 91 | +} | |
| 92 | + | |
| 93 | +sub BuildTopQueuesJS { | |
| 94 | + my ( $Self, %Param ) = @_; | |
| 95 | + my %Queues = %{ $Param{"Queues"} }; | |
| 96 | + | |
| 97 | + my @topQueues = grep { index( $Queues{$_}, '::' ) == -1 } keys %Queues; | |
| 98 | + | |
| 99 | + my $result = "\t\tif (node_id === null) { \n\t\t\treturn callback(null, [\n"; | |
| 100 | + for my $queue (@topQueues) { | |
| 101 | + | |
| 102 | + if ( grep { index( $Queues{$_}, $Queues{$queue} . "::" ) >= 0 } keys %Queues ) { | |
| 103 | + $result = $result | |
| 104 | + . "\t\t\t\t" | |
| 105 | + . '{ id: ' | |
| 106 | + . $queue | |
| 107 | + . ', label: "' | |
| 108 | + . $Self->LastQueue( $Queues{$queue} ) | |
| 109 | + . '", type: "folder" },' . "\n"; | |
| 110 | + } | |
| 111 | + else { | |
| 112 | + $result = $result | |
| 113 | + . "\t\t\t\t" | |
| 114 | + . '{ id: ' | |
| 115 | + . $queue | |
| 116 | + . ', label: "' | |
| 117 | + . $Self->LastQueue( $Queues{$queue} ) | |
| 118 | + . '", type: "link", url: "' | |
| 119 | + . $Self->{UrlAtendimento} | |
| 120 | + . $queue . '" },' . "\n"; | |
| 121 | + } | |
| 122 | + } | |
| 123 | + | |
| 124 | + $result = $result . "\t\t\t]);\n\t\t}\n"; | |
| 125 | + | |
| 126 | + return $result; | |
| 127 | +} | |
| 128 | + | |
| 129 | +sub BuildQueueJS { | |
| 130 | + my ( $Self, %Param ) = @_; | |
| 131 | + my %Queues = %{ $Param{"Queues"} }; | |
| 132 | + my $BaseQueue = $Param{"Queue"}; | |
| 133 | + my $BaseQueueID = $Param{"QueueID"}; | |
| 134 | + | |
| 135 | + # Get subqueues | |
| 136 | + my @subqueues = grep { index( $Queues{$_}, $BaseQueue . "::" ) >= 0 } keys %Queues; | |
| 137 | + my $level = () = $BaseQueue =~ /::/g; | |
| 138 | + $level = $level + 1; | |
| 139 | + | |
| 140 | + # Remove subsubqueues | |
| 141 | + @subqueues = grep { ( () = $Queues{$_} =~ /::/g ) == $level } @subqueues; | |
| 142 | + | |
| 143 | + # When there are no subqueues, there is no need to create a JS | |
| 144 | + if ( !@subqueues ) { | |
| 145 | + return; | |
| 146 | + } | |
| 147 | + | |
| 148 | + my $result = "\t\tif (node_id === " . $BaseQueueID . ") { \n\t\t\treturn callback(null, [\n"; | |
| 149 | + | |
| 150 | + for my $queue (@subqueues) { | |
| 151 | + if ( grep { index( $Queues{$_}, $Queues{$queue} . "::" ) >= 0 } keys %Queues ) { | |
| 152 | + $result = $result | |
| 153 | + . "\t\t\t\t" | |
| 154 | + . '{ id: ' | |
| 155 | + . $queue | |
| 156 | + . ', label: "' | |
| 157 | + . $Self->LastQueue( $Queues{$queue} ) | |
| 158 | + . '", type: "folder" }, ' . "\n"; | |
| 159 | + } | |
| 160 | + else { | |
| 161 | + $result = $result | |
| 162 | + . "\t\t\t\t" | |
| 163 | + . '{ id: ' | |
| 164 | + . $queue | |
| 165 | + . ', label: "' | |
| 166 | + . $Self->LastQueue( $Queues{$queue} ) | |
| 167 | + . '", type: "link", url: "' | |
| 168 | + . $Self->{UrlAtendimento} | |
| 169 | + . $queue . '" }, ' . "\n"; | |
| 170 | + } | |
| 171 | + } | |
| 172 | + | |
| 173 | + $result = $result . "\t\t\t]);\n\t\t}\n"; | |
| 174 | + | |
| 175 | + return $result; | |
| 176 | +} | |
| 177 | + | |
| 178 | +sub LastQueue { | |
| 179 | + my $Self = shift; | |
| 180 | + my $queue = shift; | |
| 181 | + my @parts = split( "::", $queue ); | |
| 182 | + return $parts[-1]; | |
| 183 | +} | |
| 184 | + | |
| 185 | +1; | ... | ... |
| 1 | +++ a/Kernel/Modules/QueuesPanelPublic.pm | |
| ... | ... | @@ -0,0 +1,205 @@ |
| 1 | +# -- | |
| 2 | +# Kernel/Modules/QueuesPanelPublic.pm - frontend module for choosing top queues | |
| 3 | +# | |
| 4 | +# Copyright (C) SeTIC - UFSC - http://setic.ufsc.br/ | |
| 5 | +# Version 01/12/2015 - Support for OTRS 4.0.3 | |
| 6 | +# | |
| 7 | +# -- | |
| 8 | +# This software comes with ABSOLUTELY NO WARRANTY. For details, see | |
| 9 | +# the enclosed file COPYING for license information (AGPL). If you | |
| 10 | +# did not receive this file, see http://www.gnu.org/licenses/agpl.txt. | |
| 11 | +# -- | |
| 12 | +package Kernel::Modules::QueuesPanelPublic; | |
| 13 | + | |
| 14 | +use strict; | |
| 15 | +use warnings; | |
| 16 | + | |
| 17 | +use Kernel::System::VariableCheck qw(:all); | |
| 18 | + | |
| 19 | +our @ObjectDependencies = ( | |
| 20 | +"Kernel::System::Web::Request", # OLD ParamObject | |
| 21 | +"Kernel::System::DB", | |
| 22 | +"Kernel::Output::HTML::Layout", | |
| 23 | +"KerneL::System::Log", | |
| 24 | +"Kernel::Config", | |
| 25 | +"Kernel::System::Queue"); | |
| 26 | + | |
| 27 | +sub new { | |
| 28 | + my ( $Type, %Param ) = @_; | |
| 29 | + | |
| 30 | + # allocate new hash for object | |
| 31 | + my $Self = {%Param}; | |
| 32 | + bless( $Self, $Type ); | |
| 33 | + | |
| 34 | + return $Self; | |
| 35 | +} | |
| 36 | + | |
| 37 | +sub Run { | |
| 38 | + my ( $Self, %Param ) = @_; | |
| 39 | + my %Data = (); | |
| 40 | + | |
| 41 | + my $ParamObject = $Kernel::OM->Get("Kernel::System::Web::Request"); | |
| 42 | + my $LayoutObject = $Kernel::OM->Get("Kernel::Output::HTML::Layout"); | |
| 43 | + my $ConfigObject = $Kernel::OM->Get("Kernel::Config"); | |
| 44 | + | |
| 45 | + ## Se recebeu o ticket, significa que usuario já está autenticado | |
| 46 | + if ( $ParamObject->GetParam( Param => "ticket" ) ) { | |
| 47 | + my $retorno = $LayoutObject->Redirect( OP => "Action=QueuesPanel", ); | |
| 48 | + $retorno =~ s/public/customer/g; | |
| 49 | + return $retorno; | |
| 50 | + } | |
| 51 | + | |
| 52 | + ## Se tiver parametro para tentar autenticar, repassa ao CAS com gateway | |
| 53 | + if ( $ParamObject->GetParam( Param => "autenticar" ) ) { | |
| 54 | + my $url = | |
| 55 | + $ConfigObject->Get('Customer::AuthModule::CAS::CASUrl') | |
| 56 | + . "/login?gateway=true&service=" | |
| 57 | + . "https://" | |
| 58 | + . $ENV{SERVER_NAME} | |
| 59 | + . $ENV{SCRIPT_NAME} | |
| 60 | + . "?Action=QueuesPanelPublic"; | |
| 61 | + return $LayoutObject->Redirect( ExtURL => $url, ); | |
| 62 | + } | |
| 63 | + | |
| 64 | + $Self->{UrlAtendimento} = '/otrs/public.pl?Action=NewTicketWizardPublic;QueueID='; | |
| 65 | + $Data{"QueueJS"} = $Self->BuildQueuesJS(); | |
| 66 | + | |
| 67 | + $Self->{Config} = $Self->{ConfigObject}->Get("Ticket::Frontend::Customer::QueuesPanel"); | |
| 68 | + my $msgChooseService = $Self->{Config}->{"MessageChooseQueuePublic"}; | |
| 69 | + $Data{MsgChooseQueue} = $msgChooseService; | |
| 70 | + | |
| 71 | + # build output | |
| 72 | + my $Output = | |
| 73 | + $LayoutObject->CustomerHeader( Title => $LayoutObject->{LanguageObject}->Translate("New ticket") ); | |
| 74 | + | |
| 75 | + $Output .= $LayoutObject->Output( | |
| 76 | + Data => \%Data, | |
| 77 | + TemplateFile => 'QueuesPanel', | |
| 78 | + ); | |
| 79 | + $Output .= $LayoutObject->CustomerFooter(); | |
| 80 | + return $Output; | |
| 81 | +} | |
| 82 | + | |
| 83 | +sub BuildQueuesJS { | |
| 84 | + my ( $Self, %Param ) = @_; | |
| 85 | + | |
| 86 | + # Get queues | |
| 87 | + my %Queues = (); | |
| 88 | + | |
| 89 | + my $DBObject = $Kernel::OM->Get("Kernel::System::DB"); | |
| 90 | + | |
| 91 | + $DBObject->Prepare( SQL => "SELECT id, name FROM queue WHERE valid_id = 1 ORDER BY name ASC", ); | |
| 92 | + while ( my @Row = $DBObject->FetchrowArray() ) { | |
| 93 | + $Queues{ $Row[0] } = $Row[1]; | |
| 94 | + } | |
| 95 | + | |
| 96 | + my $result = | |
| 97 | + '$(document).ready(function() {' . "\n\t" | |
| 98 | + . ' $("#columns").hColumns({' | |
| 99 | + . "\n\t\t" | |
| 100 | + . ' nodeSource: function(node_id, callback) {' . "\n"; | |
| 101 | + | |
| 102 | + for my $queue ( keys %Queues ) { | |
| 103 | + $result = $result . $Self->BuildQueueJS( Queues => \%Queues, Queue => $Queues{$queue}, QueueID => $queue ); | |
| 104 | + } | |
| 105 | + | |
| 106 | + $result = $result . $Self->BuildTopQueuesJS( Queues => \%Queues ); | |
| 107 | + | |
| 108 | + $result = $result . "\n\t}});\n});"; | |
| 109 | + | |
| 110 | + return $result; | |
| 111 | +} | |
| 112 | + | |
| 113 | +sub BuildTopQueuesJS { | |
| 114 | + my ( $Self, %Param ) = @_; | |
| 115 | + my %Queues = %{ $Param{"Queues"} }; | |
| 116 | + | |
| 117 | + my @topQueues = grep { index( $Queues{$_}, '::' ) == -1 } keys %Queues; | |
| 118 | + | |
| 119 | + my $result = "\t\tif (node_id === null) { \n\t\t\treturn callback(null, [\n"; | |
| 120 | + for my $queue (@topQueues) { | |
| 121 | + | |
| 122 | + if ( grep { index( $Queues{$_}, $Queues{$queue} . "::" ) >= 0 } keys %Queues ) { | |
| 123 | + $result = $result | |
| 124 | + . "\t\t\t\t" | |
| 125 | + . '{ id: ' | |
| 126 | + . $queue | |
| 127 | + . ', label: "' | |
| 128 | + . $Self->LastQueue( $Queues{$queue} ) | |
| 129 | + . '", type: "folder" },' . "\n"; | |
| 130 | + } | |
| 131 | + else { | |
| 132 | + $result = $result | |
| 133 | + . "\t\t\t\t" | |
| 134 | + . '{ id: ' | |
| 135 | + . $queue | |
| 136 | + . ', label: "' | |
| 137 | + . $Self->LastQueue( $Queues{$queue} ) | |
| 138 | + . '", type: "link", url: "' | |
| 139 | + . $Self->{UrlAtendimento} | |
| 140 | + . $queue . '" },' . "\n"; | |
| 141 | + } | |
| 142 | + } | |
| 143 | + | |
| 144 | + $result = $result . "\t\t\t]);\n\t\t}\n"; | |
| 145 | + | |
| 146 | + return $result; | |
| 147 | +} | |
| 148 | + | |
| 149 | +sub BuildQueueJS { | |
| 150 | + my ( $Self, %Param ) = @_; | |
| 151 | + my %Queues = %{ $Param{"Queues"} }; | |
| 152 | + my $BaseQueue = $Param{"Queue"}; | |
| 153 | + my $BaseQueueID = $Param{"QueueID"}; | |
| 154 | + | |
| 155 | + # Get subqueues | |
| 156 | + my @subqueues = grep { index( $Queues{$_}, $BaseQueue . "::" ) >= 0 } keys %Queues; | |
| 157 | + my $level = () = $BaseQueue =~ /::/g; | |
| 158 | + $level = $level + 1; | |
| 159 | + | |
| 160 | + # Remove subsubqueues | |
| 161 | + @subqueues = grep { ( () = $Queues{$_} =~ /::/g ) == $level } @subqueues; | |
| 162 | + | |
| 163 | + # When there are no subqueues, there is no need to create a JS | |
| 164 | + if ( !@subqueues ) { | |
| 165 | + return; | |
| 166 | + } | |
| 167 | + | |
| 168 | + my $result = "\t\tif (node_id === " . $BaseQueueID . ") { \n\t\t\treturn callback(null, [\n"; | |
| 169 | + | |
| 170 | + for my $queue (@subqueues) { | |
| 171 | + if ( grep { index( $Queues{$_}, $Queues{$queue} . "::" ) >= 0 } keys %Queues ) { | |
| 172 | + $result = $result | |
| 173 | + . "\t\t\t\t" | |
| 174 | + . '{ id: ' | |
| 175 | + . $queue | |
| 176 | + . ', label: "' | |
| 177 | + . $Self->LastQueue( $Queues{$queue} ) | |
| 178 | + . '", type: "folder" }, ' . "\n"; | |
| 179 | + } | |
| 180 | + else { | |
| 181 | + $result = $result | |
| 182 | + . "\t\t\t\t" | |
| 183 | + . '{ id: ' | |
| 184 | + . $queue | |
| 185 | + . ', label: "' | |
| 186 | + . $Self->LastQueue( $Queues{$queue} ) | |
| 187 | + . '", type: "link", url: "' | |
| 188 | + . $Self->{UrlAtendimento} | |
| 189 | + . $queue . '" }, ' . "\n"; | |
| 190 | + } | |
| 191 | + } | |
| 192 | + | |
| 193 | + $result = $result . "\t\t\t]);\n\t\t}\n"; | |
| 194 | + | |
| 195 | + return $result; | |
| 196 | +} | |
| 197 | + | |
| 198 | +sub LastQueue { | |
| 199 | + my $Self = shift; | |
| 200 | + my $queue = shift; | |
| 201 | + my @parts = split( "::", $queue ); | |
| 202 | + return $parts[-1]; | |
| 203 | +} | |
| 204 | + | |
| 205 | +1; | ... | ... |
| 1 | +++ a/Kernel/Output/HTML/Standard/QueuesPanel.tt | |
| ... | ... | @@ -0,0 +1,32 @@ |
| 1 | +# -- | |
| 2 | +# Kernel/Output/HTML/Standard/QueuesPanel.tt - overview | |
| 3 | +# | |
| 4 | +# Copyright (C) SeTIC - UFSC - http://setic.ufsc.br/ | |
| 5 | +# Version 01/12/2015 - Support for OTRS 4.0.3 | |
| 6 | +# | |
| 7 | +# -- | |
| 8 | +# $Id: writing-otrs-application.xml,v 1.1 2010/08/13 08:59:28 mg Exp $ | |
| 9 | +# -- | |
| 10 | +# This software comes with ABSOLUTELY NO WARRANTY. For details, see | |
| 11 | +# the enclosed file COPYING for license information (AGPL). If you | |
| 12 | +# did not receive this file, see http://www.gnu.org/licenses/agpl.txt. | |
| 13 | +# -- | |
| 14 | +<div class="Queues"> | |
| 15 | + <div class="ChooseQueue">[% Data.MsgChooseQueue %]</div> | |
| 16 | + | |
| 17 | + <div id="columns"></div> | |
| 18 | + | |
| 19 | + [% RenderBlockStart("ListQueue") %] | |
| 20 | + <div class="QueueCard"> | |
| 21 | + <div class="QueueTitle"><a class="QueueTitleLink" href="[% Env("Baselink") %]Action=NewTicketWizard;BaseQueueID=[% Data.QueueID %]">[% Data.QueueName %]</a></div> | |
| 22 | + <div class="QueueComments">[% Data.QueueComments %]</div> | |
| 23 | + </div> | |
| 24 | +[% RenderBlockEnd("ListQueue") %] | |
| 25 | + | |
| 26 | +[% WRAPPER JSOnDocumentComplete %] | |
| 27 | +<script type="text/javascript"> | |
| 28 | + [% Data.QueueJS %] | |
| 29 | +</script> | |
| 30 | +[% END %] | |
| 31 | + | |
| 32 | + | |
| 0 | 33 | \ No newline at end of file | ... | ... |
| 1 | +++ a/QueuesPanel.sopm | |
| ... | ... | @@ -0,0 +1,37 @@ |
| 1 | +<?xml version="1.0" encoding="utf-8" ?> | |
| 2 | +<otrs_package version="1.0"> | |
| 3 | + <Name>QueuesPanel</Name> | |
| 4 | + <Version>1.0.0</Version> | |
| 5 | + <Framework>4.0.3</Framework> | |
| 6 | + <Vendor>SeTIC</Vendor> | |
| 7 | + <URL>http://www.setic.ufsc.br</URL> | |
| 8 | + <License>GPLv2</License> | |
| 9 | + <Description>Queue choosing panel</Description> | |
| 10 | + <IntroInstall Type="post" Title="Thank you">Module installed successfully!</IntroInstall> | |
| 11 | + <Description>New Ticket Wizard</Description> | |
| 12 | + <BuildDate>?</BuildDate> | |
| 13 | + <BuildHost>?</BuildHost> | |
| 14 | + <PackageRequired>CASAuthentication</PackageRequired> | |
| 15 | + <PackageRequired>NewTicketWizard</PackageRequired> | |
| 16 | + <Filelist> | |
| 17 | + <File Permission="644" Location="Kernel/Config/Files/QueuesPanel.xml"></File> | |
| 18 | + | |
| 19 | + <File Permission="644" Location="Kernel/Language/pt_BR_QueuesPanel.pm"></File> | |
| 20 | + <File Permission="644" Location="Kernel/Language/pt_BR_QueuesPanelPublic.pm"></File> | |
| 21 | + | |
| 22 | + <File Permission="644" Location="Kernel/Modules/QueuesPanel.pm"></File> | |
| 23 | + <File Permission="644" Location="Kernel/Modules/QueuesPanelPublic.pm"></File> | |
| 24 | + | |
| 25 | + <File Permission="644" Location="Kernel/Output/HTML/Standard/QueuesPanel.tt"></File> | |
| 26 | + | |
| 27 | + <File Permission="644" Location="var/httpd/htdocs/js/thirdparty/hColumns/jquery.hcolumns.min.js"></File> | |
| 28 | + | |
| 29 | + <File Permission="644" Location="var/httpd/htdocs/skins/Customer/default/css/hColumns/hcolumns-intro.css"></File> | |
| 30 | + <File Permission="644" Location="var/httpd/htdocs/skins/Customer/default/css/hColumns/hcolumns.css"></File> | |
| 31 | + <File Permission="644" Location="var/httpd/htdocs/skins/Customer/default/css/hColumns/reset.css"></File> | |
| 32 | + | |
| 33 | + <File Permission="644" Location="var/httpd/htdocs/skins/Customer/default/images/hColumns/demo.png"></File> | |
| 34 | + <File Permission="644" Location="var/httpd/htdocs/skins/Customer/default/images/hColumns/glyphicons-halflings.png"></File> | |
| 35 | + | |
| 36 | + </Filelist> | |
| 37 | +</otrs_package> | |
| 0 | 38 | \ No newline at end of file | ... | ... |
var/httpd/htdocs/js/thirdparty/hColumns/jquery.hcolumns.min.js
0 → 100755
| 1 | +++ a/var/httpd/htdocs/js/thirdparty/hColumns/jquery.hcolumns.min.js | |
| ... | ... | @@ -0,0 +1,8 @@ |
| 1 | +// hColumns by bu <bu@hax4.in>, BSD License | |
| 2 | + | |
| 3 | +(function(b){var k={nodeSource:function(){return window.alert("dummy source, you need to create a node source")},noContentString:"There is no node here",searchPlaceholderString:"Search...",searchable:!1,customNodeTypeIndicator:{},customNodeTypeHandler:{}},l={folder:function(a,d,c){a.nodeSource(c.id,function(d,c){return d?b.error(d):a.columnView._addColumnList(c,a.columnView)})},link:function(b,d,c){return window.open(c.url)}},m={folder:"icon-chevron-right",link:"icon-globe"},h={init:function(a){var d= | |
| 4 | +b.extend(k,a),c=b.extend(l,d.customNodeTypeHandler),f=b.extend(m,d.customNodeTypeIndicator);return this.each(function(){var a=b(this),g=a.data("columnView");h.settings=d;d.columnView=h;d.handlers=c;d.indicators=f;d.container_node=this;g||(a.data("hColumn",d),a.addClass("column-view-container"),b("<div></div>").addClass("column-view-composition").appendTo(a),a.on("click",".column ul li:not('.search')",d.columnView._entryClick),d.nodeSource(null,function(a,c){return a?b.error(a):d.columnView._addColumnList(c)}))})}, | |
| 5 | +_entryClick:function(){var a=b(this).parents(".column-view-container").data("hColumn"),d=b(this).parents(".column-view-container"),c=b(this).parents(".column"),f=b(this).parents(".column").index(),e=b(this).data("node-type"),g=b(this).data("node-data");b(d).find(".column-view-composition .column:gt("+f+")").remove();c.find(".active").removeClass("active");b(this).addClass("active");return a.handlers[e](a,this,g)},_addColumnList:function(a,d){var c=d?d:this,f=b("<ul></ul>");if(0===a.length)return f= | |
| 6 | +b("<p></p>").text(d.settings.noContentString),c._addColumn(f,c);c.settings.searchable&&c._addColumnSearch(f);for(var e=0;e<a.length;e++){var g=b(document.createElement("li")).data("node-id",a[e].id).data("node-type",a[e].type).data("node-data",a[e]).attr("title",a[e].label),h=b(document.createElement("i")).addClass(c.settings.indicators[a[e].type]);g[0].appendChild(document.createTextNode(a[e].label));g[0].appendChild(h[0]);f[0].appendChild(g[0])}return c._addColumn(f,c)},_addColumnSearch:function(a){b('<li class="search"><input type="text" placeholder=" '+ | |
| 7 | +this.settings.searchPlaceholderString+'"></li>').on("keyup","input",function(a){var c=b(this).val();2<=c.length?b(this).closest("li").siblings().each(function(){""!==c&&-1===b(this).data("node-data").label.toLowerCase().indexOf(c.toLowerCase())?b(this).hide():b(this).show()}):b(this).closest("li").siblings().show()}).appendTo(a)},_addColumn:function(a,d){var c=b("<div></div>").addClass("column");c.append(a);b(d.settings.container_node).find(".column-view-composition").append(c);b(d.settings.container_node).scrollLeft(b(".column-view-composition").width())}}; | |
| 8 | +b.fn.hColumns=function(a){if(h[a])return h[a].apply(this,Array.prototype.slice.call(arguments,1));if("object"!==typeof a&&a)b.error("Method "+a+" does not exist on jQuery.hColumns");else return h.init.apply(this,arguments)}})(jQuery); | ... | ... |
var/httpd/htdocs/skins/Customer/default/css/hColumns/hcolumns-intro.css
0 → 100755
| 1 | +++ a/var/httpd/htdocs/skins/Customer/default/css/hColumns/hcolumns-intro.css | |
| ... | ... | @@ -0,0 +1,85 @@ |
| 1 | +body { | |
| 2 | + background: #f5f5f5; | |
| 3 | + font-family: "Arial", sans-serif; | |
| 4 | +} | |
| 5 | + | |
| 6 | +.container { | |
| 7 | + padding: 2em; | |
| 8 | +} | |
| 9 | + | |
| 10 | +h1 { | |
| 11 | + color: #000; | |
| 12 | + font-size: 2em; | |
| 13 | + | |
| 14 | + margin: 0.75em 0; | |
| 15 | +} | |
| 16 | + | |
| 17 | +h1 small { | |
| 18 | + color: #ccc; | |
| 19 | + font-size: 0.5em; | |
| 20 | +} | |
| 21 | + | |
| 22 | +img { | |
| 23 | + margin: 20px; | |
| 24 | +} | |
| 25 | + | |
| 26 | +h2 { | |
| 27 | + margin: 1em 0; | |
| 28 | + | |
| 29 | + font-size: 1.25em; | |
| 30 | + color: #999; | |
| 31 | +} | |
| 32 | + | |
| 33 | +ol { | |
| 34 | + margin-left: 2em; | |
| 35 | + | |
| 36 | + list-style: upper-roman; | |
| 37 | +} | |
| 38 | + | |
| 39 | +ol li { | |
| 40 | + margin: 20px; | |
| 41 | +} | |
| 42 | + | |
| 43 | +.code-block { | |
| 44 | + border: 1px solid #ccc; | |
| 45 | + background: #fff; | |
| 46 | + | |
| 47 | + margin: 1em; | |
| 48 | + padding: 1em; | |
| 49 | +} | |
| 50 | + | |
| 51 | +.code-block strong { | |
| 52 | + display: block; | |
| 53 | + | |
| 54 | + margin: 1em; | |
| 55 | + font-weight: 700; | |
| 56 | +} | |
| 57 | + | |
| 58 | +.code-block strong.minor { | |
| 59 | + font-weight: 400; | |
| 60 | + color: #666; | |
| 61 | +} | |
| 62 | + | |
| 63 | +.code-block pre { | |
| 64 | + padding: 10px; | |
| 65 | + | |
| 66 | + font-family: monospace; | |
| 67 | +} | |
| 68 | + | |
| 69 | +.code-block p { | |
| 70 | + padding: 0 30px; | |
| 71 | + | |
| 72 | + margin: 10px 0; | |
| 73 | + | |
| 74 | + font-size: 13px; | |
| 75 | +} | |
| 76 | + | |
| 77 | +.code-block ol li { | |
| 78 | + font-size: 13px; | |
| 79 | + margin: 5px; | |
| 80 | + line-height: 20px; | |
| 81 | +} | |
| 82 | + | |
| 83 | +.column-view-container { | |
| 84 | + margin: 1em; | |
| 85 | +} | ... | ... |
var/httpd/htdocs/skins/Customer/default/css/hColumns/hcolumns.css
0 → 100644
| 1 | +++ a/var/httpd/htdocs/skins/Customer/default/css/hColumns/hcolumns.css | |
| ... | ... | @@ -0,0 +1,120 @@ |
| 1 | +.ChooseQueue { | |
| 2 | + border-style: solid; | |
| 3 | + border-width: 1px; | |
| 4 | + padding: 5px; | |
| 5 | + margin-top: 5px; | |
| 6 | + margin-left: 10px; | |
| 7 | +} | |
| 8 | + | |
| 9 | +/* column view container */ | |
| 10 | +.column-view-container { | |
| 11 | + width: 100%; | |
| 12 | + height: 400px; | |
| 13 | + padding: 0; | |
| 14 | + border: 1px solid #ccc; | |
| 15 | + background: #FFF; | |
| 16 | + display: block; | |
| 17 | + overflow-x: auto; | |
| 18 | + overflow-y: hidden; | |
| 19 | +} | |
| 20 | + | |
| 21 | +/* the composition div for colums */ | |
| 22 | +.column-view-composition { | |
| 23 | + display: table; | |
| 24 | + white-space: nowrap; | |
| 25 | +} | |
| 26 | + | |
| 27 | +/**/ | |
| 28 | +.column { | |
| 29 | + display: table-cell; | |
| 30 | + border-right: 1px solid #999; | |
| 31 | +} | |
| 32 | + | |
| 33 | +.column:last-child { | |
| 34 | + border-right: 0; | |
| 35 | +} | |
| 36 | + | |
| 37 | +.column:only-child { | |
| 38 | + border-right: 1px solid #999; | |
| 39 | +} | |
| 40 | + | |
| 41 | +/* for error messages */ | |
| 42 | +.column > p { | |
| 43 | + margin: 10px; | |
| 44 | + color: #666; | |
| 45 | +} | |
| 46 | + | |
| 47 | +/* for column listing */ | |
| 48 | +.column ul { | |
| 49 | + margin: 0; | |
| 50 | + padding: 0; | |
| 51 | + height: 400px; | |
| 52 | + width: 250px; | |
| 53 | + overflow-y: auto; | |
| 54 | + list-style: none; | |
| 55 | +} | |
| 56 | + | |
| 57 | +.column ul li { | |
| 58 | + position: relative; | |
| 59 | + margin: 0; | |
| 60 | + padding: 10px 20px 10px 10px; | |
| 61 | + overflow: hidden; | |
| 62 | + -o-text-overflow: ellipsis; /* pour Opera 9 */ | |
| 63 | + text-overflow: ellipsis; /* pour le reste du monde */ | |
| 64 | +} | |
| 65 | + | |
| 66 | +.column ul li:hover { | |
| 67 | + cursor: pointer; | |
| 68 | +} | |
| 69 | + | |
| 70 | +.column ul li i { | |
| 71 | + position: absolute; | |
| 72 | + top: 9px; | |
| 73 | + right: 5px; | |
| 74 | +} | |
| 75 | + | |
| 76 | +.column ul li:hover, .column ul li.active { | |
| 77 | + background: #999999; | |
| 78 | + color: #FFFFFF; | |
| 79 | +} | |
| 80 | + | |
| 81 | +.column ul li:hover a, .column ul li.active a { | |
| 82 | + color: #FFFFFF; | |
| 83 | +} | |
| 84 | + | |
| 85 | +.column ul li.search { | |
| 86 | + margin: 0; | |
| 87 | + padding: 5px; | |
| 88 | +} | |
| 89 | + | |
| 90 | +.column ul li.search input { | |
| 91 | + width: 100%; | |
| 92 | + margin: 0; | |
| 93 | +} | |
| 94 | + | |
| 95 | + | |
| 96 | +/* icon type, could be replace with FontAwesome */ | |
| 97 | +[class^="icon-"], [class*=" icon-"] { | |
| 98 | + display: inline-block; | |
| 99 | + width: 14px; | |
| 100 | + height: 14px; | |
| 101 | + margin-top: 1px; | |
| 102 | + *margin-right: .3em; | |
| 103 | + line-height: 14px; | |
| 104 | + vertical-align: text-top; | |
| 105 | + background-image: url("../img/glyphicons-halflings.png"); | |
| 106 | + background-position: 14px 14px; | |
| 107 | + background-repeat: no-repeat; | |
| 108 | +} | |
| 109 | + | |
| 110 | +.icon-chevron-right { | |
| 111 | + background-position: -456px -72px; | |
| 112 | +} | |
| 113 | + | |
| 114 | +.icon-globe { | |
| 115 | + background-position: -336px -144px; | |
| 116 | +} | |
| 117 | + | |
| 118 | +.icon-file { | |
| 119 | + background-position: -23px -24px; | |
| 120 | +} | ... | ... |
var/httpd/htdocs/skins/Customer/default/css/hColumns/reset.css
0 → 100644
| 1 | +++ a/var/httpd/htdocs/skins/Customer/default/css/hColumns/reset.css | |
| ... | ... | @@ -0,0 +1,48 @@ |
| 1 | +/* http://meyerweb.com/eric/tools/css/reset/ | |
| 2 | + v2.0 | 20110126 | |
| 3 | + License: none (public domain) | |
| 4 | +*/ | |
| 5 | + | |
| 6 | +html, body, div, span, applet, object, iframe, | |
| 7 | +h1, h2, h3, h4, h5, h6, p, blockquote, pre, | |
| 8 | +a, abbr, acronym, address, big, cite, code, | |
| 9 | +del, dfn, em, img, ins, kbd, q, s, samp, | |
| 10 | +small, strike, strong, sub, sup, tt, var, | |
| 11 | +b, u, i, center, | |
| 12 | +dl, dt, dd, ol, ul, li, | |
| 13 | +fieldset, form, label, legend, | |
| 14 | +table, caption, tbody, tfoot, thead, tr, th, td, | |
| 15 | +article, aside, canvas, details, embed, | |
| 16 | +figure, figcaption, footer, header, hgroup, | |
| 17 | +menu, nav, output, ruby, section, summary, | |
| 18 | +time, mark, audio, video { | |
| 19 | + margin: 0; | |
| 20 | + padding: 0; | |
| 21 | + border: 0; | |
| 22 | + font-size: 100%; | |
| 23 | + font: inherit; | |
| 24 | + vertical-align: baseline; | |
| 25 | +} | |
| 26 | +/* HTML5 display-role reset for older browsers */ | |
| 27 | +article, aside, details, figcaption, figure, | |
| 28 | +footer, header, hgroup, menu, nav, section { | |
| 29 | + display: block; | |
| 30 | +} | |
| 31 | +body { | |
| 32 | + line-height: 1; | |
| 33 | +} | |
| 34 | +ol, ul { | |
| 35 | + list-style: none; | |
| 36 | +} | |
| 37 | +blockquote, q { | |
| 38 | + quotes: none; | |
| 39 | +} | |
| 40 | +blockquote:before, blockquote:after, | |
| 41 | +q:before, q:after { | |
| 42 | + content: ''; | |
| 43 | + content: none; | |
| 44 | +} | |
| 45 | +table { | |
| 46 | + border-collapse: collapse; | |
| 47 | + border-spacing: 0; | |
| 48 | +} | |
| 0 | 49 | \ No newline at end of file | ... | ... |
27.4 KB
var/httpd/htdocs/skins/Customer/default/images/hColumns/glyphicons-halflings.png
0 → 100644
12.5 KB