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