TopQuickSearch: erste version
[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
10 use Rose::Object::MakeMethods::Generic (
11  'scalar --get_set_init' => [ qw(module js) ],
12 );
13
14 my @available_modules = qw(
15   SL::Controller::TopQuickSearch::Assembly
16   SL::Controller::TopQuickSearch::Contact
17   SL::Controller::TopQuickSearch::GLTransaction
18 );
19 my %modules_by_name;
20
21 sub action_query_autocomplete {
22   my ($self) = @_;
23
24   my $hashes = $self->module->query_autocomplete;
25
26   $self->render(\ SL::JSON::to_json($hashes), { layout => 0, type => 'json', process => 0 });
27 }
28
29 sub action_select_autocomplete {
30   my ($self) = @_;
31
32   my $redirect_url = $self->module->select_autocomplete;
33
34   $self->js->redirect_to($redirect_url)->render;
35 }
36
37 sub action_do_search {
38   my ($self) = @_;
39
40   my $redirect_url = $self->module->do_search;
41
42   if ($redirect_url) {
43     $self->js->redirect_to($redirect_url)
44   }
45
46   $self->js->render;
47 }
48
49 sub available_modules {
50   my ($self) = @_;
51
52   $self->require_modules;
53
54   map { $_->new } @available_modules;
55 }
56
57 sub active_modules {
58   grep {
59     $::auth->assert($_->auth, 1)
60   } $_[0]->available_modules
61 }
62
63 sub init_module {
64   my ($self) = @_;
65
66   $self->require_modules;
67
68   die t8('Need module') unless $::form->{module};
69
70   $::lxdebug->dump(0,  "modules", \%modules_by_name);
71
72   die t8('Unknown module #1', $::form->{module}) unless my $class = $modules_by_name{$::form->{module}};
73
74   $::lxdebug->dump(0,  "auth:", $class->auth);
75
76   $::auth->assert($class->auth);
77
78   return $class->new;
79 }
80
81 sub init_js {
82   SL::ClientJS->new(controller => $_[0])
83 }
84
85 sub require_modules {
86   my ($self) = @_;
87
88   if (!$self->{__modules_required}) {
89     for my $class (@available_modules) {
90       eval "require $class" or die $@;
91       $modules_by_name{ $class->name } = $class;
92     }
93     $self->{__modules_required} = 1;
94   }
95 }
96
97 1;
98
99 __END__
100
101 =encoding utf-8
102
103 =head1 NAME
104
105 SL::Controller::TopQuickSearch - Framework for pluggable quicksearch fields in the layout top header.
106
107 =head1 SYNOPSIS
108
109 use SL::Controller::TopQuickSearch;
110 my $search = SL::Controller::TopQuickSearch->new;
111
112 # in layout
113 [%- FOREACH module = search.available_modules %]
114 <input type='text' id='top-search-[% module.name %]'>
115 [%- END %]
116
117 =head1 DESCRIPTION
118
119 This controller provides abstraction for different search plugins, and ensures
120 that all follow a common useability scheme.
121
122 Modules should be configurable, but currently are not. Diabling modules can be
123 done by removing them from available_modules.
124
125 =head1 BEHAVIOUR REQUIREMENTS
126
127 =over 4
128
129 =item *
130
131 A single text input field with the html5 placeholder containing a small
132 description of the target will be rendered from the plugin information.
133
134 =item *
135
136 On typing, the autocompletion must be enabled.
137
138 =item *
139
140 On C<Enter>, the search should redirect to an appropriate listing of matching
141 results.
142
143 If only one item matches the result, the plugin should instead redirect
144 directly to the matched item.
145
146 =item *
147
148 Search terms should accept the broadest possible matching, and if possible with
149 C<multi> parsing.
150
151 =item *
152
153 In case nothing is found, a visual indicator should be given, but no actual
154 redirect should occur.
155
156 =item *
157
158 Each search must check rights and must not present a backdoor into data that
159 the user should not see.
160
161 =back
162
163 =head1 INTERFACE
164
165 Plugins need to provide:
166
167  - name
168  - localized description for config
169  - localized description for textfield
170  - autocomplete callback
171  - redirect callback
172
173 the frontend will only generate urls of the forms:
174   action=TopQuickSearch/autocomplete&module=<module>&term=<term>
175   action=TopQuickSearch/search&module=<module>&term=<term>
176
177 =head1 TODO
178
179  - filter available searches with auth
180  - toggling with cofiguration doesn't work yet
181
182 =head1 BUGS
183
184 None yet :)
185
186 =head1 AUTHOR
187
188 Sven Schöling E<lt>s.schoeling@linet-services.deE<gt>
189
190 =cut