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