TopQuickSearch: Syntax Logik bei den Userpreferences. with_empty bei der
[kivitendo-erp.git] / SL / Controller / TopQuickSearch.pm
1 package SL::Controller::TopQuickSearch;
2
3 use strict;
4 use parent qw(SL::Controller::Base);
5
6 use SL::ClientJS;
7 use SL::JSON;
8 use SL::Locale::String qw(t8);
9 use SL::Helper::UserPreferences;
10
11 use Rose::Object::MakeMethods::Generic (
12  'scalar --get_set_init' => [ qw(module js) ],
13 );
14
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::SalesOrder',
24   'SL::Controller::TopQuickSearch::RequestForQuotation',
25   'SL::Controller::TopQuickSearch::PurchaseOrder',
26   'SL::Controller::TopQuickSearch::GLTransaction',
27   'SL::Controller::TopQuickSearch::Customer',
28   'SL::Controller::TopQuickSearch::Vendor',
29 );
30 my %modules_by_name;
31
32 sub action_query_autocomplete {
33   my ($self) = @_;
34
35   my $hashes = $self->module->query_autocomplete;
36
37   $self->render(\ SL::JSON::to_json($hashes), { layout => 0, type => 'json', process => 0 });
38 }
39
40 sub action_select_autocomplete {
41   my ($self) = @_;
42
43   my $redirect_url = $self->module->select_autocomplete;
44
45   $self->js->redirect_to($redirect_url)->render;
46 }
47
48 sub action_do_search {
49   my ($self) = @_;
50
51   my $redirect_url = $self->module->do_search;
52
53   if ($redirect_url) {
54     $self->js->redirect_to($redirect_url)
55   }
56
57   $self->js->render;
58 }
59
60 sub available_modules {
61   my ($self) = @_;
62
63   $self->require_modules;
64
65   map { $_->new } @available_modules;
66 }
67
68 sub enabled_modules {
69   my $user_prefs = SL::Helper::UserPreferences->new(
70     namespace         => 'TopQuickSearch',
71   );
72
73   my %enabled_names;
74   if (my $prefs_val = $user_prefs->get('quick_search_modules')) {
75     my @quick_search_modules = split ',', $prefs_val;
76
77     %enabled_names = map {
78       $_ => 1
79     } @quick_search_modules ;
80   } else {
81     %enabled_names = map {
82       $_ => 1
83     } @{ $::instance_conf->get_quick_search_modules };
84   }
85
86   grep {
87     $enabled_names{$_->name}
88   } $_[0]->available_modules
89 }
90
91 sub active_modules {
92   grep {
93     $::auth->assert($_->auth, 1)
94   } $_[0]->enabled_modules
95 }
96
97 sub init_module {
98   my ($self) = @_;
99
100   $self->require_modules;
101
102   die 'Need module' unless $::form->{module};
103
104   die 'Unknown module ' . $::form->{module} unless my $class = $modules_by_name{$::form->{module}};
105
106   $::auth->assert($class->auth);
107
108   return $class->new;
109 }
110
111 sub init_js {
112   SL::ClientJS->new(controller => $_[0])
113 }
114
115 sub require_modules {
116   my ($self) = @_;
117
118   if (!$self->{__modules_required}) {
119     for my $class (@available_modules) {
120       eval "require $class" or die $@;
121       $modules_by_name{ $class->name } = $class;
122     }
123     $self->{__modules_required} = 1;
124   }
125 }
126
127 1;
128
129 __END__
130
131 =encoding utf-8
132
133 =head1 NAME
134
135 SL::Controller::TopQuickSearch - Framework for pluggable quicksearch fields in the layout top header.
136
137 =head1 SYNOPSIS
138
139   use SL::Controller::TopQuickSearch;
140   my $search = SL::Controller::TopQuickSearch->new;
141   $::request->layout->add_javascripts('kivi.QuickSearch.js');
142
143   # in template
144   [%- FOREACH module = search.enabled_modules %]
145   <input type='text' id='top-search-[% module.name %]'>
146   [%- END %]
147
148 =head1 DESCRIPTION
149
150 This controller provides abstraction for different search plugins, and ensures
151 that all follow a common useability scheme.
152
153 Modules should be configurable per user, but currently are not. Disabling
154 modules can be done by removing them from available_modules or in client_config.
155
156 =head1 BEHAVIOUR REQUIREMENTS
157
158 =over 4
159
160 =item *
161
162 A single text input field with the html5 placeholder containing a small
163 description of the target will be rendered from the plugin information.
164
165 =item *
166
167 On typing, the autocompletion must be enabled.
168
169 =item *
170
171 On C<Enter>, the search should redirect to an appropriate listing of matching
172 results.
173
174 If only one item matches the result, the plugin should instead redirect
175 directly to the matched item.
176
177 =item *
178
179 Search terms should accept the broadest possible matching, and if possible with
180 C<multi> parsing.
181
182 =item *
183
184 In case nothing is found, a visual indicator should be given, but no actual
185 redirect should occur.
186
187 =item *
188
189 Each search must check rights and must not present a backdoor into data that
190 the user should not see.
191
192 =item *
193
194 By design the search must not try to guess C<exact matches>.
195
196 =back
197
198 =head1 INTERFACE
199
200 The full interface is described in L<SL::Controller::TopQuickSeach::Base>
201
202 =head1 TODO
203
204   * user configuration
205
206 =head1 BUGS
207
208 None yet :)
209
210 =head1 AUTHOR
211
212 Sven Schöling E<lt>s.schoeling@linet-services.deE<gt>
213
214 =cut