1 package SL::Controller::TopQuickSearch;
4 use parent qw(SL::Controller::Base);
8 use SL::Locale::String qw(t8);
9 use SL::Helper::UserPreferences;
11 use Rose::Object::MakeMethods::Generic (
12 'scalar --get_set_init' => [ qw(module js) ],
15 my @available_modules = (
16 'SL::Controller::TopQuickSearch::Article',
17 'SL::Controller::TopQuickSearch::Part',
18 'SL::Controller::TopQuickSearch::Service',
19 'SL::Controller::TopQuickSearch::Assembly',
20 'SL::Controller::TopQuickSearch::Assortment',
21 'SL::Controller::TopQuickSearch::Contact',
22 'SL::Controller::TopQuickSearch::SalesQuotation',
23 'SL::Controller::TopQuickSearch::SalesOrderIntake',
24 'SL::Controller::TopQuickSearch::SalesOrder',
25 'SL::Controller::TopQuickSearch::SalesDeliveryOrder',
26 'SL::Controller::TopQuickSearch::RequestForQuotation',
27 'SL::Controller::TopQuickSearch::PurchaseQuotationIntake',
28 'SL::Controller::TopQuickSearch::PurchaseOrder',
29 'SL::Controller::TopQuickSearch::PurchaseOrderConfirmation',
30 'SL::Controller::TopQuickSearch::PurchaseDeliveryOrder',
31 'SL::Controller::TopQuickSearch::GLTransaction',
32 'SL::Controller::TopQuickSearch::Customer',
33 'SL::Controller::TopQuickSearch::Vendor',
34 'SL::Controller::TopQuickSearch::PhoneNumber',
35 'SL::Controller::TopQuickSearch::Project',
39 sub action_query_autocomplete {
42 my $hashes = $self->module->query_autocomplete;
44 $self->render(\ SL::JSON::to_json($hashes), { layout => 0, type => 'json', process => 0 });
47 sub action_select_autocomplete {
50 my $redirect_url = $self->module->select_autocomplete;
52 $self->js->redirect_to($redirect_url)->render;
55 sub action_do_search {
58 my $redirect_url = $self->module->do_search;
61 $self->js->redirect_to($redirect_url)
67 sub available_modules {
70 $self->require_modules;
72 map { $_->new } @available_modules;
76 my $user_prefs = SL::Helper::UserPreferences->new(
77 namespace => 'TopQuickSearch',
80 my @quick_search_modules;
81 if (my $prefs_val = $user_prefs->get('quick_search_modules')) {
82 @quick_search_modules = split ',', $prefs_val;
84 @quick_search_modules = @{ $::instance_conf->get_quick_search_modules };
87 my %enabled_names = map { $_ => 1 } @quick_search_modules;
90 $enabled_names{$_->name}
91 } $_[0]->available_modules
96 !$_->auth || $::auth->assert($_->auth, 1)
97 } $_[0]->enabled_modules
103 $self->require_modules;
105 die 'Need module' unless $::form->{module};
107 die 'Unknown module ' . $::form->{module} unless my $class = $modules_by_name{$::form->{module}};
109 $::auth->assert($class->auth) if $class->auth;
115 SL::ClientJS->new(controller => $_[0])
118 sub require_modules {
121 if (!$self->{__modules_required}) {
122 for my $class (@available_modules) {
123 eval "require $class" or die $@;
124 $modules_by_name{ $class->name } = $class;
126 $self->{__modules_required} = 1;
138 SL::Controller::TopQuickSearch - Framework for pluggable quicksearch fields in the layout top header.
142 use SL::Controller::TopQuickSearch;
143 my $search = SL::Controller::TopQuickSearch->new;
144 $::request->layout->add_javascripts('kivi.QuickSearch.js');
147 [%- FOREACH module = search.enabled_modules %]
148 <input type='text' id='top-search-[% module.name %]'>
153 This controller provides abstraction for different search plugins, and ensures
154 that all follow a common useability scheme.
156 Modules should be configurable per user, but currently are not. Disabling
157 modules can be done by removing them from available_modules or in client_config.
159 =head1 BEHAVIOUR REQUIREMENTS
165 A single text input field with the html5 placeholder containing a small
166 description of the target will be rendered from the plugin information.
170 On typing, the autocompletion must be enabled.
174 On C<Enter>, the search should redirect to an appropriate listing of matching
177 If only one item matches the result, the plugin should instead redirect
178 directly to the matched item.
182 Search terms should accept the broadest possible matching, and if possible with
187 In case nothing is found, a visual indicator should be given, but no actual
188 redirect should occur.
192 Each search must check rights and must not present a backdoor into data that
193 the user should not see.
197 By design the search must not try to guess C<exact matches>.
203 The full interface is described in L<SL::Controller::TopQuickSeach::Base>
215 Sven Schöling E<lt>s.schoeling@linet-services.deE<gt>