View | Details | Raw Unified | Return to bug 14899
Collapse All | Expand All

(-)a/Koha/Objects.pm (+12 lines)
Lines 190-195 sub reset { Link Here
190
    return $self;
190
    return $self;
191
}
191
}
192
192
193
=head3 Koha::Objects->delete();
194
195
Koha::Objects->delete();
196
197
=cut
198
199
sub delete {
200
    my ( $self ) = @_;
201
202
    return $self->_resultset->delete;
203
}
204
193
=head3 Koha::Objects->as_list();
205
=head3 Koha::Objects->as_list();
194
206
195
Koha::Objects->as_list();
207
Koha::Objects->as_list();
(-)a/admin/searchengine/elasticsearch/mappings.pl (+137 lines)
Line 0 Link Here
1
#!/usr/bin/perl
2
3
# This file is part of Koha.
4
#
5
# Koha is free software; you can redistribute it and/or modify it
6
# under the terms of the GNU General Public License as published by
7
# the Free Software Foundation; either version 3 of the License, or
8
# (at your option) any later version.
9
#
10
# Koha is distributed in the hope that it will be useful, but
11
# WITHOUT ANY WARRANTY; without even the implied warranty of
12
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
# GNU General Public License for more details.
14
#
15
# You should have received a copy of the GNU General Public License
16
# along with Koha; if not, see <http://www.gnu.org/licenses>.
17
18
use Modern::Perl;
19
use CGI;
20
use C4::Koha;
21
use C4::Output;
22
use C4::Auth;
23
24
use Koha::ElasticSearch;
25
use Koha::SearchMarcMaps;
26
use Koha::SearchFields;
27
28
my $input = new CGI;
29
my ( $template, $borrowernumber, $cookie ) = get_template_and_user(
30
    {   template_name   => 'admin/searchengine/elasticsearch/mappings.tt',
31
        query           => $input,
32
        type            => 'intranet',
33
        authnotrequired => 0,
34
        flagsrequired   => { superlibrarian => 1 },                          # Create a specific permission?
35
    }
36
);
37
38
my $index = $input->param('index') || 'biblios';
39
my $op    = $input->param('op')    || 'list';
40
my @messages;
41
42
my $database = Koha::Database->new();
43
my $schema   = $database->schema;
44
45
my $marc_type = lc C4::Context->preference('marcflavour');
46
47
if ( $op eq 'edit' ) {
48
49
    $schema->storage->txn_begin;
50
51
    my @field_name = $input->param('search_field_name');
52
    my @field_label = $input->param('search_field_label');
53
    my @field_type = $input->param('search_field_type');
54
55
    my @index_name          = $input->param('mapping_index_name');
56
    my @search_field_name  = $input->param('mapping_search_field_name');
57
    my @mapping_sort        = $input->param('mapping_sort');
58
    my @mapping_facet       = $input->param('mapping_facet');
59
    my @mapping_suggestible = $input->param('mapping_suggestible');
60
    my @mapping_marc_field  = $input->param('mapping_marc_field');
61
62
    eval {
63
64
        for my $i ( 0 .. scalar(@field_name) - 1 ) {
65
            my $field_name = $field_name[$i];
66
            my $field_label = $field_label[$i];
67
            my $field_type = $field_type[$i];
68
            # We cannot use Koha::SearchFields because of the ->type method ...
69
            my $search_field = $schema->resultset('SearchField')->find({ name => $field_name }, { key => 'name' });
70
            $search_field->label($field_label);
71
            $search_field->type($field_type);
72
            $search_field->update;
73
        }
74
75
        Koha::SearchMarcMaps->search( { marc_type => $marc_type, } )->delete;
76
77
        for my $i ( 0 .. scalar(@index_name) - 1 ) {
78
            my $index_name          = $index_name[$i];
79
            my $search_field_name  = $search_field_name[$i];
80
            my $mapping_marc_field  = $mapping_marc_field[$i];
81
            my $mapping_facet       = $mapping_facet[$i];
82
            my $mapping_suggestible = $mapping_suggestible[$i];
83
            my $mapping_sort        = $mapping_sort[$i];
84
            $mapping_sort = undef if $mapping_sort eq 'undef';
85
86
            my $search_field = Koha::SearchFields->find({ name => $search_field_name }, { key => 'name' });
87
            # TODO Check mapping format
88
            my $marc_field = Koha::SearchMarcMaps->find_or_create({ index_name => $index_name, marc_type => $marc_type, marc_field => $mapping_marc_field });
89
            $search_field->add_to_search_marc_maps($marc_field, { facet => $mapping_facet, suggestible => $mapping_suggestible, sort => $mapping_sort } );
90
91
        }
92
    };
93
    if ($@) {
94
        push @messages, { type => 'error', code => 'error_on_update', message => $@, };
95
        $schema->storage->txn_rollback;
96
    } else {
97
        push @messages, { type => 'message', code => 'success_on_update' };
98
        $schema->storage->txn_commit;
99
    }
100
}
101
102
my @indexes;
103
104
for my $index_name (qw| biblios authorities |) {
105
    my $search_fields = $schema->resultset('SearchField')->search(
106
        { 'search_marc_map.index_name' => $index_name, 'search_marc_map.marc_type' => $marc_type, },
107
        {   join => { search_marc_to_fields => 'search_marc_map' },
108
            '+select' => [ 'search_marc_to_fields.facet', 'search_marc_to_fields.suggestible', 'search_marc_to_fields.sort', 'search_marc_map.marc_field' ],
109
            '+as'     => [ 'facet',                       'suggestible',                       'sort',                       'marc_field' ],
110
        }
111
    );
112
113
    my @mappings;
114
    while ( my $s = $search_fields->next ) {
115
        push @mappings,
116
          { search_field_name  => $s->name,
117
            search_field_label => $s->label,
118
            search_field_type  => $s->type,
119
            marc_field         => $s->get_column('marc_field'),
120
            sort               => $s->get_column('sort') // 'undef', # To avoid warnings "Use of uninitialized value in lc"
121
            suggestible        => $s->get_column('suggestible'),
122
            facet              => $s->get_column('facet'),
123
          };
124
    }
125
126
    push @indexes, { index_name => $index_name, mappings => \@mappings };
127
}
128
129
my $search_fields = $schema->resultset('SearchField')->search;
130
my @all_search_fields = $search_fields->search( {}, { order_by => ['name'] } );
131
$template->param(
132
    indexes           => \@indexes,
133
    all_search_fields => \@all_search_fields,
134
    messages          => \@messages,
135
);
136
137
output_html_with_http_headers $input, $cookie, $template->output;
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/searchengine/elasticsearch/mappings.tt (-1 / +298 lines)
Line 0 Link Here
0
- 
1
[% INCLUDE 'doc-head-open.inc' %]
2
<title>Koha &rsaquo; Administration &rsaquo; Elastic Search mappings</title>
3
[% INCLUDE 'doc-head-close.inc' %]
4
<script type="text/javascript" src="[% interface %]/lib/jquery/plugins/jquery.tablednd.js"></script>
5
<script type="text/javascript">
6
    function clean_line( line ) {
7
        $(line).find('input[type="text"]').val("");
8
        $(line).find('select').find('option:first').attr("selected", "selected");
9
    }
10
11
    function clone_line( line ) {
12
        var new_line = $(line).clone();
13
        $(new_line).removeClass("nodrag nodrop");
14
        $(new_line).find('td:last-child>a').removeClass("add").addClass("delete").html(_("Delete"));
15
        $(new_line).find('[data-id]').each( function() {
16
            $(this).attr({ name: $(this).attr('data-id') }).removeAttr('data-id');
17
        } );
18
        $(new_line).find("select").each( function() {
19
            var attr = $(this).attr('name');
20
            var val = $(line).find('[data-id="' + attr + '"]').val();
21
            $(this).find('option[value="' + val + '"]').attr("selected", "selected");
22
        } );
23
        return new_line;
24
    }
25
26
    $(document).ready(function() {
27
        $("#tabs").tabs();
28
        $('.delete').click(function() {
29
            $(this).parents('tr').remove();
30
        });
31
32
        $("table.mappings").tableDnD( {
33
            onDragClass: "dragClass",
34
        } );
35
        $('.add').click(function() {
36
            var table = $(this).closest('table');
37
            var index_name   = $(table).attr('data-index_name');
38
            var line = $(this).closest("tr");
39
            var marc_field = $(line).find('input[data-id="mapping_marc_field"]').val();
40
            if ( marc_field.length > 0 ) {
41
                var new_line = clone_line( line );
42
                new_line.appendTo($('table[data-index_name="'+index_name+'"]>tbody'));
43
                $('.delete').click(function() {
44
                    $(this).parents('tr').remove();
45
                });
46
                clean_line(line);
47
48
                $(table).tableDnD( {
49
                    onDragClass: "dragClass",
50
                } );
51
            }
52
        });
53
    });
54
</script>
55
<style type="text/css">
56
a.add, a.delete {
57
    cursor: pointer;
58
}
59
</style>
60
</head>
61
<body id="admin_searchengine_mappings" class="admin">
62
[% INCLUDE 'header.inc' %]
63
[% INCLUDE 'cat-search.inc' %]
64
65
<div id="breadcrumbs"><a href="/cgi-bin/koha/mainpage.pl">Home</a> &rsaquo; <a href="/cgi-bin/koha/admin/admin-home.pl">Administration</a> &rsaquo; Search engine configuration</div>
66
67
<div id="doc3" class="yui-t1">
68
69
  <div id="bd">
70
    <div id="yui-main">
71
    <div class="yui-b">
72
73
    [% FOR m IN messages %]
74
      <div class="dialog [% m.type %]">
75
        [% SWITCH m.code %]
76
        [% CASE 'error_on_update' %]
77
          An error occurred when updateing mappings ([% m.message %]).
78
        [% CASE 'error_on_delete' %]
79
          An error occurred when deleting the existing mappings. Nothing has been changed!
80
          (search field [% m.values.field_name %] with mapping [% m.values.marc_field %].)
81
        [% CASE 'success_on_update' %]
82
          Mapping updated successfully.
83
        [% CASE %]
84
          [% m.code %]
85
        [% END %]
86
      </div>
87
    [% END %]
88
89
    <h1>Search engine configuration</h1>
90
    <div class="warning">
91
        Warning: Any modification in these configurations will need a total reindexation to be fully taken into account !
92
    </div>
93
    [% IF errors %]
94
        <div class="error">
95
        Errors occurred, Modifications does not apply. Please check following values:
96
          <ul>
97
            [% FOREACH e IN errors %]
98
                <li>
99
                    [% IF ( e.type == "malformed_mapping" ) %]
100
                        The value "[% e.value %]" is not supported for mappings
101
                    [% ELSIF ( e.type == "no_mapping" ) %]
102
                        There is no mapping for the index [% e.value %]
103
                    [% END %]
104
                </li>
105
            [% END %]
106
          </ul>
107
        </div>
108
    [% END %]
109
110
    <form method="post">
111
        <input type="hidden" name="op" value="edit" />
112
        <div id="tabs" class="toptabs" style="clear:both">
113
            <ul>
114
                <li><a href="#search_fields">Search fields</a></li>
115
                [% FOREACH index IN indexes %]
116
                    [% SWITCH index.index_name %]
117
                        [% CASE 'biblios' %]<li><a href="#mapping_biblios">Biblios</a></li>
118
                        [% CASE 'authorities' %]<li><a href="#mapping_authorities">Authorities</a></li>
119
                    [% END %]
120
                [% END %]
121
            </ul>
122
            <div id="search_fields">
123
              <table class="search_fields">
124
                <thead>
125
                  <tr>
126
                    <th>Name</th>
127
                    <th>Label</th>
128
                    <th>Type</th>
129
                  </tr>
130
                </thead>
131
                <tbody>
132
                  [% FOREACH search_field IN all_search_fields %]
133
                    <tr>
134
                      <td>
135
                        <input type="text" name="search_field_name" value="[% search_field.name %]" />
136
                      </td>
137
                      <td><input type="text" name="search_field_label" value="[% search_field.label %]" />
138
                      <td>
139
                        <select name="search_field_type">
140
                          <option value=""></option>
141
                          [% IF search_field.type == "string" %]
142
                            <option value="string" selected="selected">String</option>
143
                          [% ELSE %]
144
                            <option value="string">String</option>
145
                          [% END %]
146
                          [% IF search_field.type == "date" %]
147
                            <option value="date" selected="selected">Date</option>
148
                          [% ELSE %]
149
                            <option value="date">Date</option>
150
                          [% END %]
151
                          [% IF search_field.type == "number" %]
152
                            <option value="number" selected="selected">Number</option>
153
                          [% ELSE %]
154
                            <option value="number">Number</option>
155
                          [% END %]
156
                          [% IF search_field.type == "boolean" %]
157
                            <option value="boolean" selected="selected">Boolean</option>
158
                          [% ELSE %]
159
                            <option value="boolean">Boolean</option>
160
                          [% END %]
161
                          [% IF search_field.type == "sum" %]
162
                            <option value="sum" selected="selected">Sum</option>
163
                          [% ELSE %]
164
                            <option value="sum">Sum</option>
165
                          [% END %]
166
                        </select>
167
                      </td>
168
                    </tr>
169
                  [% END %]
170
                </tbody>
171
              </table>
172
            </div>
173
            [% FOREACH index IN indexes %]
174
                <div id="mapping_[% index.index_name %]">
175
                    <table class="mappings" data-index_name="[% index.index_name%]">
176
                      <thead>
177
                        <tr class="nodrag nodrop">
178
                          <th>Search field</th>
179
                          <th>Sortable</th>
180
                          <th>Facetable</th>
181
                          <th>Suggestible</th>
182
                          <th>Mapping</th>
183
                          <th></th>
184
                        </tr>
185
                      </thead>
186
                      <tbody>
187
                        [% FOREACH mapping IN index.mappings %]
188
                          <tr>
189
                            <td>
190
                              <input type="hidden" name="mapping_index_name" value="[% index.index_name %]" />
191
                              <input type="hidden" name="mapping_search_field_name" value="[% mapping.search_field_name %]">
192
                              [% mapping.search_field_label %]
193
                            </td>
194
                            <td>
195
                              <select name="mapping_sort">
196
                                [% IF mapping.sort == 'undef' %]
197
                                  <option value="undef" selected="selected">Undef</option>
198
                                [% ELSE %]
199
                                  <option value="undef">Undef</option>
200
                                [% END %]
201
                                [% IF mapping.sort == 0 %]
202
                                  <option value="0" selected="selected">0</option>
203
                                [% ELSE %]
204
                                  <option value="0">0</option>
205
                                [% END %]
206
                                [% IF  mapping.sort == 1 %]
207
                                  <option value="1" selected="selected">1</option>
208
                                [% ELSE %]
209
                                  <option value="1">1</option>
210
                                [% END %]
211
                              </select>
212
                            </td>
213
                            <td>
214
                              <select name="mapping_facet">
215
                                [% IF mapping.facet %]
216
                                  <option value="0">No</option>
217
                                  <option value="1" selected="selected">Yes</option>
218
                                [% ELSE %]
219
                                  <option value="0" selected="selected">No</option>
220
                                  <option value="1">Yes</option>
221
                                [% END %]
222
                              </selected>
223
                            </td>
224
                            <td>
225
                              <select name="mapping_suggestible">
226
                                [% IF mapping.suggestible %]
227
                                  <option value="0">No</option>
228
                                  <option value="1" selected="selected">Yes</option>
229
                                [% ELSE %]
230
                                  <option value="0" selected="selected">No</option>
231
                                  <option value="1">Yes</option>
232
                                [% END %]
233
                              </selected>
234
                            </td>
235
                            <td>
236
                                <input name="mapping_marc_field" type="text" value="[% mapping.marc_field %]" />
237
                            </td>
238
                            <td><a class="delete" style="cursor: pointer;">Delete</a></td>
239
                          </tr>
240
                        [% END %]
241
                      </tbody>
242
                      <tfoot>
243
                        <tr class="nodrag nodrop">
244
                          <td>
245
                            <input data-id="mapping_index_name" type="hidden" value="[% index.index_name %]" />
246
                            <select data-id="mapping_search_field_name">
247
                             [% FOREACH f IN all_search_fields %]
248
                               <option value="[% f.name %]">[% f.name %]</option>
249
                             [% END %]
250
                            /select>
251
                          </td>
252
                          <td>
253
                            <select data-id="mapping_sort">
254
                              <option value="undef">Undef</option>
255
                              <option value="0">0</option>
256
                              <option value="1">1</option>
257
                            </select>
258
                          </td>
259
                          <td>
260
                            <select data-id="mapping_facet">
261
                              [% IF mapping.facet %]
262
                                <option value="0">No</option>
263
                                <option value="1" selected="selected">Yes</option>
264
                              [% ELSE %]
265
                                <option value="0" selected="selected">No</option>
266
                                <option value="1">Yes</option>
267
                              [% END %]
268
                            </selected>
269
                          </td>
270
                          <td>
271
                            <select data-id="mapping_suggestible">
272
                              [% IF mapping.suggestible %]
273
                                <option value="0">No</option>
274
                                <option value="1" selected="selected">Yes</option>
275
                              [% ELSE %]
276
                                <option value="0" selected="selected">No</option>
277
                                <option value="1">Yes</option>
278
                              [% END %]
279
                            </selected>
280
                          </td>
281
                          <td><input data-id="mapping_marc_field" type="text" /></td>
282
                          <td><a class="add">Add</a></td>
283
                        </tr>
284
                      </tfoot>
285
                    </table>
286
                </div>
287
            [% END %]
288
        </div>
289
        <p><input type="submit" value="Save" /></p>
290
    </form>
291
</div>
292
293
</div>
294
<div class="yui-b">
295
[% INCLUDE 'admin-menu.inc' %]
296
</div>
297
</div>
298
[% INCLUDE 'intranet-bottom.inc' %]

Return to bug 14899