From 3bcda99e767623d6d929642c789a578f5478088a Mon Sep 17 00:00:00 2001 From: Marcel de Rooy Date: Thu, 29 Jun 2023 08:49:38 +0000 Subject: [PATCH] Bug 33537: Add staff template and script Content-Type: text/plain; charset=utf-8 Test plan: Go to Administration/SMTP Servers. Click Domain limits. Do some CRUD operations. Bonus: Add another tab with domain limits. Edit or remove records on tab 1. Try CRUD on changed or removed records on tab 2. Signed-off-by: Marcel de Rooy [EDIT] Added some preventDefault calls, as suggested by JD. --- admin/domain_limits.pl | 35 +++ .../prog/en/modules/admin/domain_limits.tt | 111 ++++++++ .../prog/en/modules/admin/smtp_servers.tt | 1 + .../intranet-tmpl/prog/js/domain_limits.js | 246 ++++++++++++++++++ 4 files changed, 393 insertions(+) create mode 100755 admin/domain_limits.pl create mode 100644 koha-tmpl/intranet-tmpl/prog/en/modules/admin/domain_limits.tt create mode 100644 koha-tmpl/intranet-tmpl/prog/js/domain_limits.js diff --git a/admin/domain_limits.pl b/admin/domain_limits.pl new file mode 100755 index 0000000000..b6679a19ee --- /dev/null +++ b/admin/domain_limits.pl @@ -0,0 +1,35 @@ +#!/usr/bin/perl + +# Copyright 2023 Rijksmuseum, Koha development team +# +# This file is part of Koha. +# +# Koha is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# Koha is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Koha; if not, see . + +use Modern::Perl; +use CGI qw ( -utf8 ); + +use C4::Auth qw( get_template_and_user ); +use C4::Output qw( output_html_with_http_headers ); + +my $input = CGI->new; +my ( $template, $borrowernumber, $cookie ) = get_template_and_user( + { + template_name => "admin/domain_limits.tt", + query => $input, + type => "intranet", + flagsrequired => { parameters => 'manage_smtp_servers' }, + } +); +output_html_with_http_headers $input, $cookie, $template->output; diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/domain_limits.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/domain_limits.tt new file mode 100644 index 0000000000..a830de71a7 --- /dev/null +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/domain_limits.tt @@ -0,0 +1,111 @@ +[% USE raw %] +[% USE Asset %] +[% SET footerjs = 1 %] + +[% INCLUDE 'doc-head-open.inc' %] +Domain limits › Administration › Koha +[% INCLUDE 'doc-head-close.inc' %] + + + +[% INCLUDE 'header.inc' %] +[% INCLUDE 'prefs-admin-search.inc' %] + +[% BLOCK modal_form %] + +[% END %] + +[% WRAPPER 'sub-header.inc' %] + [% WRAPPER breadcrumbs %] + [% WRAPPER breadcrumb_item %] + Administration + [% END %] + [% WRAPPER breadcrumb_item bc_active= 1 %] + Domain limits + [% END %] + [% END #/ WRAPPER breadcrumbs %] +[% END #/ WRAPPER sub-header.inc %] + +
+
+
+
+ + + + + + +

Domain limits

+
+ + + + + + + + + + + +
DomainMessage limitUnitsUnit typeBelongs toActions
+ [% INCLUDE modal_form %] +
+ +
+
+ +
+ +
+
+ + +[% MACRO jsinclude BLOCK %] + [% Asset.js("js/admin-menu.js") | $raw %] + [% INCLUDE 'datatables.inc' %] + [% Asset.js("js/domain_limits.js") | $raw %] +[% END %] + +[% INCLUDE 'intranet-bottom.inc' %] diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/smtp_servers.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/smtp_servers.tt index 83e6c628bd..07afa84259 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/smtp_servers.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/smtp_servers.tt @@ -248,6 +248,7 @@

SMTP servers

diff --git a/koha-tmpl/intranet-tmpl/prog/js/domain_limits.js b/koha-tmpl/intranet-tmpl/prog/js/domain_limits.js new file mode 100644 index 0000000000..69ddb768d4 --- /dev/null +++ b/koha-tmpl/intranet-tmpl/prog/js/domain_limits.js @@ -0,0 +1,246 @@ +// domain_limits.js: Code for the corresponding admin form + +var domain_limits_table; +$(document).ready(function() { + domain_limits_table = init_table(); + $('#toolbar').on( "click", 'a.add', function (ev) { + ev.preventDefault(); + start_modal( 'add' ); + }); + $('#domain_limits').on( "click", 'a.add_member', function (ev) { + ev.preventDefault(); + start_modal( 'add_member', { belongs_to: $(this).parents('tr').attr('id') } ); + }); + $('#domain_limits').on( "click", 'a.edit, a.edit_member', function (ev) { + ev.preventDefault(); + hide_dialogs(); + var limit_id = $(this).parents('tr').attr('id'); + api_get(limit_id); + }); + $('#domain_limits').on( "click", 'a.delete', function (ev) { + ev.preventDefault(); + hide_dialogs(); + if ( window.confirm( _("Delete this limit?") ) ) { + var limit_id = $(this).parents('tr').attr('id'); + api_delete( limit_id ); + } + }); + $('#domain_limits_modal').on( 'keydown', function(ev) { + if ( ev.which == 27 ) { // respond to escape key + $('#domain_limits_modal').hide(); + return false; + } + }); + $('#domain_limits_modal button.save').on( 'click', function() { + if ( !$('#domain_limits_modal form').get(0).checkValidity() ) return; // Do not return false here to allow validation. + var limit_id = $('#domain_limits_modal .modal-form').data('id'); + var row = get_modal_inputs(); + if ( limit_id ) api_put(limit_id, row); else api_post(row); + return false; + }); + $('#domain_limits_modal button.cancel').on( 'click', function() { + $('#domain_limits_modal').hide(); + return false; + }); +}); + +function api_get (limit_id) { + var row = domain_limits_table.DataTable().row('#'+limit_id).data(); + $.ajax({ + method: "GET", + url: '/api/v1/smtp/domain_limits/' + limit_id, + }).done(function (data) { + start_modal( row.belongs_to ? 'edit_member' : 'edit', data ); + }).fail(function (xhr) { + status_message( 'get', xhr.status, row ); + }); +} + +function api_delete (limit_id) { + var limit_name = domain_limits_table.DataTable().row('#'+limit_id).data().domain_name; + $.ajax({ + method: "DELETE", + url: '/api/v1/smtp/domain_limits/' + limit_id, + }).done(function () { + domain_limits_table.api().ajax.reload(); + $('#domain_limit_message').html( _("Limit for '%s' deleted.").format(limit_name) ).show(); + }).fail(function (xhr) { + status_message( 'delete', xhr.status, { domain_name: limit_name } ); + }); +} + +function api_post (row) { + $.ajax({ + method: "POST", + url: '/api/v1/smtp/domain_limits', + data: JSON.stringify(row), + contentType: 'application/json', + }).done(function () { + domain_limits_table.api().ajax.reload(); + $('#domain_limit_message').html( _("Limit for '%s' added.").format(row['domain_name']) ).show(); + }).fail(function (xhr, status, error) { + status_message( 'post', xhr.status, row ); + }).always(function () { + $('#domain_limits_modal').hide(); + });; +} + +function api_put (limit_id, row) { + $.ajax({ + method: "PUT", + url: '/api/v1/smtp/domain_limits/' + limit_id, + data: JSON.stringify(row), + contentType: 'application/json', + }).done(function () { + domain_limits_table.api().ajax.reload(); + $('#domain_limit_message').html( _("Limit for '%s' modified.").format(row.domain_name) ).show(); + }).fail(function (xhr, status, error) { + status_message( 'put', xhr.status, row ); + }).always(function () { + $('#domain_limits_modal').hide(); + }); +} + +function status_message (method, status, row) { // only used in ajax.fail + // Extending with parsing xhr.responseText seems not needed here (now). + // POST and PUT may trigger similar exceptions, GET and DELETE are trivial. + var messages = { + delete : _( "Deleting limit for '%s' failed." ), + get : _( "Retrieving limit for '%s' failed." ), + put : _( "Modifying limit for '%s' failed." ), + post : _( "Adding limit for '%s' failed." ), + status_400 : _( " (Status 400 - Bad request: expected columns were empty.)" ), + status_401 : _( " (Status 401 - Unauthorized: session may have expired.)" ), + status_403 : _( " (Status 403 - Forbidden: check permissions.)" ), + status_404 : _( " (Status 404 - Not found)" ), + status_404_put : _( " (Status 404 - Not found: group domain does not exist)" ), + status_404_post : _( " (Status 404 - Not found: group domain does not exist)" ), + status_409 : _( " (Status 409 - Conflict: duplicate domain name.)" ), + }; + var str = messages['status_'+status+'_'+method] || messages['status_'+status] || ''; + $( '#domain_limit_alert' ).html( messages[method].format(row.domain_name) + str ).show(); +} + +function hide_dialogs () { + $('div.dialog').html('').hide(); +} + +function get_actions_html (row) { + var result = ''; + if ( row.belongs_to == undefined ) { + result += ' '+_("Edit")+''+"\n"; + result += ' '+_("Delete")+''+"\n"; + result += ' '+_("New member")+''+"\n"; + } else { + result += ' '+_("Edit")+''+"\n"; + result += ' '+_("Delete")+''+"\n"; + } + return result; +} + +function get_modal_inputs () { + var row = {}; + row.domain_name = $('input[name="domain_name"]').val(); + if( $('input[name="group_domain"]:visible').length ) { + row.belongs_to = $('#domain_limits_modal .modal-form').data('belongs_to'); + } else { + row.domain_limit = $('input[name="domain_limit"]').val(); + row.units = $('input[name="units"]').val(); + row.unit_type = $('select[name="unit_type"]').val(); + } + return row; +} + +function toggle_modal_inputs (action) { + hide_dialogs(); + // Show one title + $('h3.modal-title').hide().filter('.'+action).show() + // Hide and disable some inputs (disable needed to skip validation) + $('.modal-body li').hide().filter('.'+action).show(); + $('.modal-body .toggle_validation').prop('disabled', true); + $('.modal-body li.'+action+' .toggle_validation').prop('disabled', false); +} + +function fill_modal_inputs (action, row) { + // Start by clearing + $('#domain_limits_modal input').val(''); + $('#domain_limits_modal select').val(''); + + if ( action=='edit' ) { + for ( const field_name of [ 'domain_name', 'domain_limit', 'units' ] ) { + $('#domain_limits_modal input[name="'+field_name+'"]').val(row[field_name]); + } + $('#domain_limits_modal select').val(row['unit_type']); + } else if ( action=='edit_member' ) { + $('#domain_limits_modal input[name="domain_name"]').val(row.domain_name); + $('#domain_limits_modal input[name="group_domain"]').val(row.group_domain); + } else if( action=='add_member' ) { + $('#domain_limits_modal input[name="group_domain"]').val(row.group_domain); + } +} + +function start_modal (action, row) { + toggle_modal_inputs(action); + $('#domain_limits_modal .modal-form').data('id', row ? row.domain_limit_id : null).data('belongs_to', row ? row.belongs_to : null); + if( action=='add_member' ) { + // fetch group domain name from corresponding row + var group_domain = domain_limits_table.DataTable().row('#' + row.belongs_to).data().domain_name; + fill_modal_inputs( action, { group_domain: group_domain } ); + } else { + fill_modal_inputs(action, row); + } + $('#domain_limits_modal').show().find('input')[0].focus(); +} + +function init_table () { + return $("#domain_limits").kohaTable({ + "ajax": { + "url": '/api/v1/smtp/domain_limits', + }, + 'language': { + 'emptyTable': '
'+_("There are no domain limits defined.")+'
' + }, + "columnDefs": [ { + "targets": [0,1,2,3,4], + "render": function (data, type, row, meta) { + if ( type == 'display' && data != null ) { + return data.escapeHtml(); + } + return data; + } + } ], + "columns": [ + { + "data": "domain_name", + "searchable": true, + "orderable": true, + }, + { + "data": "domain_limit", + "searchable": true, + "orderable": true, + }, + { + "data": "units", + "searchable": true, + "orderable": true, + }, + { + "data": "unit_type", + "searchable": true, + "orderable": true, + }, + { + "data": "group_domain", + "searchable": false, + "orderable": false, + }, + { + "data": function( row, type, val, meta ) { return get_actions_html(row) }, + "searchable": false, + "orderable": false + } + ], + rowId: 'domain_limit_id', + }); +} -- 2.30.2