Bug 20388: Elasticsearch - Ability to add search fields from UI

Test plan:

  - apply this patch,
  - check that SearchEngine system preference is set to Elasticsearch,
  - go to Admin > Search engine configuration,
  - on the search fields tab, fill a new line at the bottom of the table
    (name, label, type)
  - click on the "Add" button and save,
  - check that the new search field has been saved,
  - also test field deletions,
  - check that you can't delete already mapped fields.

Signed-off-by: Nicolas Legrand <nicolas.legrand@bulac.fr>
Signed-off-by: Séverine QUEUNE <severine.queune@bulac.fr>

Signed-off-by: Nick Clemens <nick@bywatersolutions.com>
Signed-off-by: Björn Nylén <bjorn.nylen@ub.lu.se>
Signed-off-by: Julian Maurice <julian.maurice@biblibre.com>
Signed-off-by: Michal Denar <black23@gmail.com>

Signed-off-by: Michal Denar <black23@gmail.com>
Signed-off-by: Michaela Sieber <michaela.sieber@kit.edu>
Signed-off-by: David Schmidt <davewood@gmx.at>
Signed-off-by: Nick Clemens <nick@bywatersolutions.com>
Signed-off-by: Katrin Fischer <katrin.fischer@bsz-bw.de>
This commit is contained in:
Alex Arnaud 2021-04-07 13:20:53 +00:00 committed by Katrin Fischer
parent 0e4677d3ef
commit 0607e6adfa
Signed by: kfischer
GPG key ID: 0EF6E2C03357A834
5 changed files with 148 additions and 7 deletions

View file

@ -68,6 +68,18 @@ sub search_marc_maps {
return $marc_map_fields;
}
=head3 is_mapped
my $is_mapped = $search_field->is_mapped
=cut
sub is_mapped {
my ( $self ) = @_;
return $self->search_marc_maps()->count ? 1 : 0;
}
=head3 is_mapped_biblios
my $is_mapped_biblios = $search_field->is_mapped_biblios

View file

@ -109,6 +109,8 @@ if ( $op eq 'cud-edit' ) {
eval {
Koha::SearchFields->search()->delete;
for my $i ( 0 .. scalar(@field_name) - 1 ) {
my $field_name = $field_name[$i];
my $field_label = $field_label[$i];
@ -117,9 +119,11 @@ if ( $op eq 'cud-edit' ) {
my $field_staff_client = $field_staff_client[$i];
my $field_opac = $field_opac[$i];
my $search_field = Koha::SearchFields->find( { name => $field_name }, { key => 'name' } );
$search_field->label($field_label);
$search_field->type($field_type);
my $search_field = Koha::SearchFields->find_or_create({
name => $field_name,
label => $field_label,
type => $field_type,
});
if (!length($field_weight)) {
$search_field->weight(undef);
@ -285,6 +289,7 @@ my @all_search_fields;
while ( my $search_field = $search_fields->next ) {
my $search_field_unblessed = $search_field->unblessed;
$search_field_unblessed->{mapped_biblios} = 1 if $search_field->is_mapped_biblios;
$search_field_unblessed->{is_mapped} = $search_field->is_mapped;
$search_field_unblessed->{aliases} = $search_fields_aliases->{$search_field_unblessed->{name}};
push @all_search_fields, $search_field_unblessed;
}

View file

@ -133,7 +133,7 @@ a.add, a.delete {
[% WRAPPER tab_panels %]
[% WRAPPER tab_panel tabname="search_fields" bt_active= 1 %]
<table class="search_fields" id="search_fields_table">
<table class="search_fields" id="search_fields_table" data-index_name="search_fields">
<thead>
<tr>
<th>Name</th>
@ -142,11 +142,13 @@ a.add, a.delete {
<th>Type</th>
<th>Weight</th>
<th colspan="2">Searchable</th>
<th>&nbsp;</th>
</tr>
<tr>
<th colspan="5" class="NoSort">&nbsp;</th>
<th class="NoSort">Staff interface</th>
<th class="NoSort">OPAC</th>
<th>&nbsp;</th>
</tr>
</thead>
<tbody>
@ -253,9 +255,56 @@ a.add, a.delete {
[% END %]
</select>
</td>
<td>
[% IF search_field.is_mapped %]
<a class="btn btn-default btn-xs disabled delete" style="cursor: pointer;"><i class="fa fa-trash"></i> Delete</a>
[% ELSE %]
<a class="btn btn-default btn-xs delete" style="cursor: pointer;"><i class="fa fa-trash"></i> Delete</a>
[% END %]
</td>
</tr>
[% END %]
</tbody>
<tfoot>
<tr>
<td>
<input type="text" data-id="search_field_name"/>
</td>
<td></td>
<td>
<input type="text" data-id="search_field_label"/>
</td>
<td>
<select data-id="search_field_type">
<option value=""></option>
<option value="string">String</option>
<option value="date">Date</option>
<option value="year">Year</option>
<option value="number">Number</option>
<option value="boolean">Boolean</option>
<option value="sum">Sum</option>
<option value="isbn">ISBN</option>
<option value="stdno">Std. Number</option>
</select>
</td>
<td>
<input type="text" data-id="search_field_weight" value="">
</td>
<td>
<select data-id="search_field_staff_client">
<option value="1">Yes</option>
<option value="0">No</option>
</select>
</td>
<td>
<select data-id="search_field_opac">
<option value="1">Yes</option>
<option value="0">No</option>
</select>
</td>
<td><a class="btn btn-default btn-xs add-search-field"><i class="fa fa-plus"></i> Add</a></td>
</tr>
</tfoot>
</table>
[% END %]
[% FOREACH index IN indexes %]

View file

@ -14,6 +14,7 @@ function clone_line(line) {
$(new_line).find("select").each(function () {
var attr = $(this).attr('name');
var val = $(line).find('[data-id="' + attr + '"]').val();
$(this).find('option').removeAttr('selected');
$(this).find('option[value="' + val + '"]').attr("selected", "selected");
});
return new_line;
@ -46,7 +47,7 @@ $(document).ready(function () {
tableInit( oldtabid, newtabid );
});
$('.delete').click(function () {
$(document).on('click', '.delete', function() {
if ($(this).hasClass('mandatory') && $(".mandatory[data-field_name=" + $(this).attr('data-field_name') + "]").length < 2) {
alert( __("This field is mandatory and must have at least one mapping") );
return;
@ -54,6 +55,25 @@ $(document).ready(function () {
var table = $(this).closest('table');
let dt = $(table).DataTable();
dt.row( $(this).closest('tr') ).remove().draw();
$(this).parents('tr').remove();
var line = $(this).closest("tr");
var name;
// We clicked delete button on search fields tab.
if (name = $(line).find('input[name="search_field_name"]').val()) {
// Prevent user from using a search field for a mapping
// after removing it without saving.
$('select[data-id="mapping_search_field_name"]').each(function( index, element) {
$(element).find('option[value="' + name + '"]').remove();
});
}
var search_field_name = $(line).find('input[name="mapping_search_field_name"]').val();
var mappings = $('input[name="mapping_search_field_name"][type="hidden"][value="' + search_field_name + '"]');
if (mappings.length == 0) {
var search_field_line = $('input[name="search_field_name"][value="' + search_field_name + '"]').closest("tr");
$(search_field_line).find('a.btn-default').removeClass('disabled');
}
}
});
@ -65,10 +85,16 @@ $(document).ready(function () {
var marc_field = $(line).find('input[data-id="mapping_marc_field"]').val();
if (marc_field.length > 0) {
var new_line = clone_line(line);
var search_field_name = $(line).find('select[data-id="mapping_search_field_name"] option:selected').text();
new_line.appendTo($('table[data-index_name="' + index_name + '"]>tbody'));
let dt = $('#' + table_id).DataTable();
dt.row.add(new_line).draw();
var search_field_line = $('input[name="search_field_name"][value="' + search_field_name + '"]').closest("tr");
$(search_field_line).find('a.btn-default').addClass('disabled');
clean_line(line);
$(table).on( 'click', '.delete', function () {
var table = $(this).closest('table');
let dt = $(table).DataTable();
@ -99,4 +125,26 @@ $(document).ready(function () {
});
return true;
});
$('.add-search-field').click(function() {
var table = $(this).closest('table');
var line = $(this).closest("tr");
var name = $(line).find('input[data-id="search_field_name"]').val();
let already_exist = 0;
if ( $('input[name="search_field_name"][value="' + name + '"]').val() ) {
already_exist = 1;
}
if (already_exist) {
alert("SearchField "+ name + " already exist");
} else {
var label = $(line).find('input[data-id="search_field_label"]').val();
if ( name.length > 0 && label.length > 0 ) {
var new_line = clone_line( line );
new_line.appendTo(table.find('tbody'));
clean_line(line);
}
}
});
});

View file

@ -19,10 +19,11 @@
use Modern::Perl;
use Test::More tests => 10;
use Test::More tests => 12;
use Koha::Database;
use Koha::SearchFields;
use Koha::SearchMarcMaps;
use t::lib::Mocks;
use t::lib::TestBuilder;
@ -38,6 +39,32 @@ my $sf = $builder->build({
source => 'SearchField',
});
my $search_field = Koha::SearchFields->find($sf->{id});
ok(!$search_field->is_mapped, 'Search field 1 is not mapped');
my $auth_smm = $builder->build({
source => 'SearchMarcMap',
value => {
index_name => 'authorities',
marc_type => 'marc21',
marc_field => '200abde'
}
});
my $auth_smtf = $builder->build({
source => 'SearchMarcToField',
value => {
search_marc_map_id => $auth_smm->{id},
search_field_id => $sf->{id}
}
});
$search_field = Koha::SearchFields->find($sf->{id});
ok($search_field->is_mapped, 'Search field 1 is mapped');
Koha::SearchMarcMaps->search({})->delete;
$schema->resultset('SearchMarcToField')->search({})->delete;
my $smm = $builder->build({
source => 'SearchMarcMap',
value => {
@ -72,7 +99,7 @@ my $smtf2 = $builder->build({
}
});
my $search_field = Koha::SearchFields->find($sf->{id});
$search_field = Koha::SearchFields->find($sf->{id});
my $marc_maps = $search_field->search_marc_maps;
my $marc_map = $marc_maps->next;
is($marc_maps->count, 1, 'search_marc_maps should return 1 marc map');