From 24aad09781412287ff56fcf52656190adac37a72 Mon Sep 17 00:00:00 2001
From: Owen Leonard <oleonard@myacpl.org>
Date: Fri, 5 Feb 2021 18:28:15 +0000
Subject: [PATCH] Bug 27644: Add button to SQL report editor for inserting
 runtime parameters

This patch adds a button menu to the SQL report CodeMirror editor for
inserting runtime parameters. Each menu item triggers a modal dialog
where the user can specify a parameter label and any other relevant
option.

To test, apply the patch and rebuild the staff client CSS
(https://wiki.koha-community.org/wiki/Working_with_SCSS_in_the_OPAC_and_staff_client).

- Go to Reports -> Use saved.
- Create or edit a report.
- You should see a menu button above the SQL editor field, "Insert
  runtime parameter."
- The menu should contain the options "Authorized value," "Date," "Item
  types," "Libraries," "Patron categories," and "Text field."
- Test each option. Each should trigger the display of a modal dialog
  with a heading which corresponds to your choice.
- In all cases except the "Authorized value" choice you should see a
  single form field for "label."
- Enter text in the label field and click the "Insert parameter" button.
- The correct runtime parameter should be inserted into the SQL editor.
  - If you placed a cursor somewhere in the SQL editor first, your
    parameter should be inserted in that location in the editor.
  - If you selected some text in the editor before selecting a
    parameter, the paramter should replace the selected text.
- In the case of the "Authorized value" selection, the modal dialog
  should include both a label field and a field for choosing an
  authorized value category.
- Try submitting the form without selecting an authorized value. It
  should warn you that the field is required.
- After testing the authorized value selection, try inserting another
  parameter to confirm that the authorized value selection (now hidden)
  is no longer required.
---
 .../intranet-tmpl/prog/css/src/staff-global.scss   |  18 +++
 .../en/modules/reports/guided_reports_start.tt     | 148 ++++++++++++++++++++-
 2 files changed, 163 insertions(+), 3 deletions(-)

diff --git a/koha-tmpl/intranet-tmpl/prog/css/src/staff-global.scss b/koha-tmpl/intranet-tmpl/prog/css/src/staff-global.scss
index e250462415..6680373a1c 100644
--- a/koha-tmpl/intranet-tmpl/prog/css/src/staff-global.scss
+++ b/koha-tmpl/intranet-tmpl/prog/css/src/staff-global.scss
@@ -951,6 +951,12 @@ fieldset {
                 width: unset;
             }
         }
+
+        .dropdown-menu {
+            li {
+                padding-bottom: 0;
+            }
+        }
     }
 }
 
@@ -1709,6 +1715,18 @@ i {
     white-space: nowrap;
 }
 
+.form-group {
+    label {
+        display: block;
+        margin-bottom: 5px;
+    }
+
+    div {
+        &.hint {
+            margin: 5px 0;
+        }
+    }
+}
 
 .blocker {
     color: #990000;
diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/reports/guided_reports_start.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/reports/guided_reports_start.tt
index ada04bb135..1255d193b7 100644
--- a/koha-tmpl/intranet-tmpl/prog/en/modules/reports/guided_reports_start.tt
+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/reports/guided_reports_start.tt
@@ -1,5 +1,6 @@
 [% USE raw %]
 [% USE Asset %]
+[% USE AuthorisedValues %]
 [% USE KohaDates %]
 [% USE Koha %]
 [% USE TablesSettings %]
@@ -1211,10 +1212,21 @@
 
                         <fieldset class="rows">
                             <legend>SQL:</legend>
-                            <div style="margin:1em;">
+                                <div class="btn-group"  style="margin-left:30px;">
+                                    <button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
+                                        Insert runtime parameter <span class="caret"></span>
+                                    </button>
+                                    <ul class="dropdown-menu">
+                                        <li><a href="#" class="insertParam" id="insertAuthVal">Authorized value</a></li>
+                                        <li><a href="#" class="insertParam" id="insertDate">Date</a></li>
+                                        <li><a href="#" class="insertParam" id="insertItemtypes">Item types</a></li>
+                                        <li><a href="#" class="insertParam" id="insertBranches">Libraries</a></li>
+                                        <li><a href="#" class="insertParam" id="insertCategorycode">Patron categories</a></li>
+                                        <li><a href="#" class="insertParam" id="insertText">Text field</a></li>
+                                    </ul>
+                                </div>
                                 <textarea id="sql" name="sql" class="required" required="required" cols="50" rows="10">[% sql | html %]</textarea>
-                                <span class="required">Required</span>
-                            </div>
+                                <span class="required" style="margin-left:30px;">Required</span>
                         </fieldset>
 
                         <fieldset class="action">
@@ -1292,6 +1304,40 @@
         </div> <!-- /.col-sm-2.col-sm-pull-10 -->
     </div> <!-- /.row -->
 
+    <!-- Runtime Parameters Modal -->
+    <div class="modal" id="runtime_parameters" tabindex="-1" role="dialog" aria-labelledby="runtime_parametersLabel">
+        <div class="modal-dialog" role="document">
+            <div class="modal-content">
+                <div class="modal-header">
+                    <button type="button" class="closebtn" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
+                    <h4 class="modal-title" id="runtime_parametersLabel">Runtime parameter options</h4>
+                </div>
+                <form id="send_runtime_parameter">
+                    <input type="hidden" name="param_category" id="param_category" />
+                    <div class="modal-body">
+                        <div class="form-group">
+                            <label for="paramLabel">Parameter label: </label>
+                            <input class="form-control" type="text" name="paramLabel" id="paramLabel">
+                            <div class="hint">Optional. The label for the field shown when the report is run, e.g. "Select a library."</div>
+                        </div>
+                        <div id="authorised_value_category" class="form-group" style="display:none">
+                            <label for="authorised_value">Authorized value category:</label>
+                            <select class="form-control" name="authorised_value" id="authorised_value" size="1">
+                                <option value=""></option>
+                                [% PROCESS options_for_authorised_value_categories authorised_value_categories => AuthorisedValues.GetCategories() %]
+                            </select>
+                            <div class="hint">Select which authorized value category the user will choose from.</div>
+                        </div>
+                    </div> <!-- /.modal-body -->
+                    <div class="modal-footer">
+                        <button type="submit" id="sendParam" class="btn btn-default approve">Insert parameter</button>
+                        <button type="button" class="btn btn-default deny" data-dismiss="modal">Cancel</button>
+                    </div> <!-- /.modal-footer -->
+                </form> <!-- /#send_runtime_parameter -->
+            </div> <!-- /.modal-content -->
+        </div> <!-- /.modal-dialog -->
+    </div> <!-- /#runtime_parameters -->
+
 [% MACRO jsinclude BLOCK %]
     [% Asset.js("js/charts.js") | $raw %]
     [% Asset.js("lib/d3c3/d3.min.js") | $raw %]
@@ -1375,6 +1421,62 @@
                 smartIndent: false
             });
 
+            $(document).ready(function(){
+                $(".insertParam").on("click", function(e){
+                    e.preventDefault();
+                    var category = this.id;
+                    showParamModal( category );
+                });
+
+                $("#runtime_parameters").on("shown.bs.modal", function(){
+                    $("#paramLabel").focus();
+                });
+
+                $("#runtime_parameters").on("hide.bs.modal", function(){
+                    $("#send_runtime_parameter")[0].reset();
+                    $("#authorised_value_category").val("").hide();
+                    $("#authorised_value").prop("required", false ).removeAttr("required");
+                });
+
+                $("#send_runtime_parameter").on("submit", function(e){
+                    e.preventDefault();
+                    /* Get form values */
+                    var paramLabel = $("#paramLabel").val();
+                    var param_category = $("#param_category").val();
+                    var categoryLabel = $("#authorised_value").val();
+                    // Get CodeMirror environment variables
+                    var selection = editor.getSelection();
+                    var doc = editor.getDoc();
+                    var cursor = doc.getCursor();
+                    var pos = {
+                        line: cursor.line,
+                        ch: cursor.ch
+                    }
+                    /* Build runtime parameter text string */
+                    var text = "";
+                    if( paramLabel && param_category ){
+                        text += paramLabel + "|" + param_category;
+                    } else if( paramLabel ) {
+                        text += paramLabel;
+                    } else if( param_category ){
+                        text += param_category;
+                    }
+                    if( text != "" ){
+                        text = " <<" + text + ">> ";
+                        if( selection.length > 0){
+                            editor.replaceSelection(text);
+                        } else {
+                            doc.replaceRange(text, pos);
+                        }
+                    }
+                    $("#runtime_parameters").modal("hide");
+                });
+
+                $("#authorised_value").on("change", function(){
+                    $("#param_category").val( $(this).val() );
+                });
+            })
+
             // https://stackoverflow.com/questions/2086287/how-to-clear-jquery-validation-error-messages#answer-16025232
             function clearValidation( formElement ){
                 // formElement should be a jQuery object
@@ -1398,6 +1500,46 @@
             });
         [% END %]
 
+        function showParamModal( category ){
+            var modal = $("#runtime_parameters");
+            var modalTitle = $("#runtime_parametersLabel");
+            switch ( category ){
+                case "insertAuthVal":
+                    modalTitle.text( _("Insert authorized value parameter") );
+                    $("#paramLabel").val("Authorized value")
+                    $("#authorised_value_category").show();
+                    $("#authorised_value").prop("required", true ).attr("required", "required");
+                    break;
+                case "insertDate":
+                    modalTitle.text( _("Insert date parameter") );
+                    $("#paramLabel").val("Date")
+                    $("#param_category").val("date");
+                    break;
+                case "insertItemtypes":
+                    modalTitle.text( _("Insert item types parameter") );
+                    $("#paramLabel").val("Item type")
+                    $("#param_category").val("itemtypes");
+                    break;
+                case "insertBranches":
+                    modalTitle.text( _("Insert libraries parameter") );
+                    $("#paramLabel").val("Library")
+                    $("#param_category").val("branches");
+                    break;
+                case "insertCategorycode":
+                    modalTitle.text( _("Insert patron category parameter") );
+                    $("#paramLabel").val("Patron category")
+                    $("#param_category").val("categorycode");
+                    break;
+                case "insertText":
+                    modalTitle.text( _("Insert text parameter") );
+                    $("#paramLabel").val("Text")
+                    $("#param_category").val("");
+                    break;
+            }
+            $("#paramLabel").select();
+            modal.modal("show");
+        }
+
         function load_group_subgroups () {
             var group = $("#group_select").val();
             var sg = $("#subgroup");
-- 
2.11.0