From aeeb64b0d3ba3c92f3d854a0e5b88a493257b373 Mon Sep 17 00:00:00 2001
From: Kyle M Hall <kyle@bywatersolutions.com>
Date: Mon, 24 Feb 2020 12:06:17 -0500
Subject: [PATCH] Bug 24857: Add volume management to detail.pl

Signed-off-by: Andrew Fuerste-Henry <andrew@bywatersolutions.com>

Signed-off-by: Rebecca  Coert <rcoert@arlingtonva.us>
---
 .../prog/en/modules/catalogue/detail.tt            | 287 +++++++++++++++++++++
 1 file changed, 287 insertions(+)

diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/catalogue/detail.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/catalogue/detail.tt
index efbf34fb5d..51d7102cbf 100644
--- a/koha-tmpl/intranet-tmpl/prog/en/modules/catalogue/detail.tt
+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/catalogue/detail.tt
@@ -184,6 +184,7 @@
             <a href="#holdings">Holdings ([% itemloop.size() || 0 | html %])</a>
         </li>
     [% END %]
+[% IF Koha.Preference('EnableVolumes') %]<li><a href="#volumes">Volumes</a></li>[% END %]
 [% IF ( MARCNOTES || notes ) %]<li><a href="#description">Descriptions ([% ( MARCNOTES.size || 1 ) | html %])</a></li>[% END %]
 [% IF ( subscriptionsnumber ) %]<li><a href="#subscriptions">Subscriptions</a></li>[% END %]
 [% IF Koha.Preference('AcquisitionDetails') %]<li><a href="#acq_details">Acquisition details</a></li>[% END %]
@@ -483,6 +484,23 @@ Note that permanent location is a code, and location may be an authval.
     </table>
 [% END %][%# end of block items_table %]
 
+[% IF Koha.Preference('EnableVolumes') %]
+    <div id="volumes">
+        <div class="volumes_table_table_controls">
+            <a href="#" class="volume-create btn btn-default btn-xs"><i class="fa fa-plus"></i> Create new</a>
+        </div>
+        <table class="volumes-table" id="volumes-table">
+            <thead>
+                <tr>
+                    <td>Display Order</td>
+                    <td>Description</td>
+                    <td>&nbsp;</td>
+                </tr>
+            </thead>
+        </table>
+    </div>
+[% END %]
+
 <div id="holdings">
 
 [% IF ( Koha.Preference('NovelistSelectStaffEnabled') && Koha.Preference('NovelistSelectStaffProfile') && Koha.Preference('NovelistSelectStaffView') == 'above' ) %]
@@ -899,6 +917,88 @@ Note that permanent location is a code, and location may be an authval.
 
 [% END %]
 
+<div class="modal fade" id="modal-volume-create" tabindex="-1" role="dialog" aria-labelledby="modal-volume-create-label">
+    <div class="modal-dialog">
+        <div class="modal-content">
+            <div class="modal-header">
+                <button type="button" class="closebtn" data-dismiss="modal" aria-hidden="true">×</button>
+                <h3 id="modal-volume-create-label"><i class="fa fa-plus"></i> Create a new volume</h3>
+            </div>
+            <form id="modal-volume-create-form" class="validated">
+                <div class="modal-body">
+                    <fieldset>
+                        <p>
+                            <label for="volume_description" class="required">Name: </label>
+                            <input name="description" id="modal-volume-create-form-description" type="text" size="30" required="required" class="required" />
+                            <span class="required">Required</span>
+                        </p>
+                        <p>
+                            <label for="volume_display_order" class="required">Display order: </label>
+                            <input name="display_order" id="modal-volume-create-form-display_order" value="0" type="number" size="5" required="required" class="required" />
+                            <span class="required">Required</span>
+                            <br/>
+                            <span class="hint">Numbers only, volumes will be displayed in counting order</span>
+                        </p>
+                    </fieldset>
+                </div>
+                <div class="modal-footer">
+                    <button id="modal-volume-create-submit" class="btn btn-default"><i class="fa fa-plus"></i> Submit</button>
+                    <button class="btn btn-link" data-dismiss="modal" aria-hidden="true">Cancel</button>
+                </div>
+            </form>
+        </div>
+    </div>
+</div>
+
+<div class="modal fade" id="modal-volume-edit" tabindex="-1" role="dialog" aria-labelledby="modal-volume-edit-label">
+    <div class="modal-dialog">
+        <div class="modal-content">
+            <div class="modal-header">
+                <button type="button" class="closebtn" data-dismiss="modal" aria-hidden="true">×</button>
+                <h3 id="modal-volume-edit-label"><i class='fa fa-edit'></i> Edit volume</h3>
+            </div>
+            <form id="modal-volume-edit-form" class="validated">
+                <div class="modal-body">
+                    <fieldset>
+                        <p>
+                            <label for="volume_description" class="required">Name: </label>
+                            <input name="description" id="modal-volume-edit-form-description" type="text" size="30" required="required" class="required" />
+                            <span class="required">Required</span>
+                        </p>
+                        <p>
+                            <label for="volume_display_order" class="required">Sort order: </label>
+                            <input name="display_order" id="modal-volume-edit-form-display_order" type="number" size="5" />
+                            <span class="hint">Numbers only, volumes will be displayed in counting order</span>
+                        </p>
+                    </fieldset>
+                </div>
+                <div class="modal-footer">
+                    <button id="modal-volume-edit-submit" class="btn btn-default"><i class='fa fa-edit'></i> Submit</button>
+                    <button class="btn btn-link" data-dismiss="modal" aria-hidden="true">Cancel</button>
+                </div>
+            </form>
+        </div>
+    </div>
+</div>
+
+<div class="modal fade" id="modal-volume-delete" tabindex="-1" role="dialog" aria-labelledby="modal-volume-create-label">
+    <div class="modal-dialog">
+        <div class="modal-content">
+            <div class="modal-header">
+                <button type="button" class="closebtn" data-dismiss="modal" aria-hidden="true">×</button>
+                <h3 id="modal-volume-delete-label"><i class='fa fa-trash'></i> Delete volume</h3>
+            </div>
+            <div class="modal-body">
+                Are you sure you want to delete this volume?
+            </div>
+            <div class="modal-footer">
+                <button id="modal-volume-delete-submit" class="btn btn-danger"><i class='fa fa-trash'></i> Delete</button>
+                <button class="btn btn-link" data-dismiss="modal" aria-hidden="true">Cancel</button>
+            </div>
+        </div>
+    </div>
+</div>
+
 [% MACRO jsinclude BLOCK %]
     [% INCLUDE 'catalog-strings.inc' %]
     [% Asset.js("js/catalog.js") | $raw %]
@@ -1162,6 +1262,193 @@ Note that permanent location is a code, and location may be an authval.
                 }));
             [% END %]
         });
+
+        [% IF Koha.Preference('EnableVolumes') %]
+            // Load volumes table
+            var volumesTable = KohaTable("volumes-table", {
+                "bAutoWidth": false,
+                'sDom': '<"top pager"ilp>t<"bottom pager"ip>r',
+                "aoColumns": [
+                    {
+                        "mDataProp": function( oObj ) {
+                            return oObj.display_order;
+                        },
+                    },
+                    {
+                        "mDataProp": function( oObj ) {
+                            return oObj.description;
+                        },
+                    },
+                    {
+                        "mDataProp": function( oObj ) {
+                            return `<button class='volume-edit btn btn-default btn-xs' data-volume-id='${oObj.volume_id}'>
+                                <i class='fa fa-edit'></i> ${_('Edit')}
+                            </button>`
+                            + '&nbsp'
+                            + `<button class='volume-delete btn btn-default btn-xs' data-volume-id='${oObj.volume_id}'>
+                                <i class='fa fa-trash'></i> ${('Delete')}
+                            </button>`;
+                        },
+                    },
+                ],
+                "bPaginate": false,
+                "bProcessing": true,
+                "bServerSide": false,
+                "sAjaxSource": `/api/v1/biblios/${biblionumber}/volumes`,
+                "sAjaxDataProp": "",
+                "fnServerData": function ( sSource, aoData, fnCallback ) {
+                    $.getJSON( sSource, aoData, function (json) {
+                        fnCallback(json)
+                    } );
+                },
+            });
+
+            // Create new volumes
+            $('.volume-create').on('click', function(){
+                $('#modal-volume-create-form-description').val("");
+                $('#modal-volume-create-submit').removeAttr('disabled');
+                $('#modal-volume-create').modal('show');
+            });
+
+            $("#modal-volume-create-form").validate({
+                submitHandler: function(form) {
+                    $.ajax({
+                        url: `/api/v1/biblios/${biblionumber}/volumes`,
+                        headers: { "x-koha-embed": "items" },
+                        success: function(volumes){
+                            $('#modal-volume-create-submit').attr('disabled', 'disabled');
+
+                            var settings = {
+                              "url": `/api/v1/biblios/${biblionumber}/volumes`,
+                              "method": "POST",
+                              "headers": {
+                                "Content-Type": "application/json"
+                              },
+                              "data": JSON.stringify(
+                                  {
+                                      "description": $("#modal-volume-create-form-description").val(),
+                                      "display_order": $("#modal-volume-create-form-display_order").val(),
+                                  }
+                              ),
+                            };
+
+                            $.ajax(settings)
+                            .done(function (response) {
+                                $('#volume-add-form-select').append($('<option>', {
+                                    value: response.volume_id,
+                                    text: response.description
+                                }));
+
+                                $('#modal-volume-create').modal('hide');
+                                if ( volumes.length == 0 ) {
+                                    // This bib has no previous volumes, reload the page
+                                    window.location.replace(`/cgi-bin/koha/catalogue/detail.pl?biblionumber=${biblionumber}`);
+                                } else {
+                                    // Has other volumes, just reload the table
+                                    volumesTable.api().ajax.reload();
+                                }
+                            })
+                            .fail(function(err) {
+                                var message = err.responseJSON.error;
+                                alert(message);
+                            });
+                        }
+                    });
+                }
+            });
+
+            $('#modal-volume-create').on('shown.bs.modal', function () {
+                $('#modal-volume-create-form-description').focus();
+            })
+
+            // Edit existing volumes
+            $('body').on( 'click', '.volume-edit', function(){
+                const volume_id = $(this).data('volume-id');
+                const url = `/api/v1/biblios/${biblionumber}/volumes/${volume_id}`;
+                $.get( url, function( data ) {
+                    $('#modal-volume-edit-form-description').val( data.description );
+                    $('#modal-volume-edit-form-display_order').val( data.display_order );
+                    $('#modal-volume-edit-submit').data('volume-id', volume_id );
+                    $('#modal-volume-edit-submit').removeAttr('disabled');
+                    $('#modal-volume-edit').modal('show');
+                });
+            });
+
+            $("#modal-volume-edit-form").validate({
+                submitHandler: function(form) {
+                    $('#modal-volume-edit-submit').attr('disabled', 'disabled');
+
+                    const volume_id = $('#modal-volume-edit-submit').data('volume-id');
+                    const url = `/api/v1/biblios/${biblionumber}/volumes/${volume_id}`;
+
+                    var settings = {
+                      "url": url,
+                      "method": "PUT",
+                      "headers": {
+                        "Content-Type": "application/json"
+                      },
+                      "data": JSON.stringify(
+                          {
+                              "description": $("#modal-volume-edit-form-description").val(),
+                              "display_order": $("#modal-volume-edit-form-display_order").val(),
+                          }
+                      ),
+                    };
+
+                    $.ajax(settings)
+                    .done(function (response) {
+                        $('#modal-volume-edit').modal('hide');
+                        volumesTable.api().ajax.reload();
+                    })
+                    .fail(function(err) {
+                        var message = err.responseJSON.error;
+                        alert(message);
+                    });
+                }
+            });
+
+            $('#modal-volume-edit').on('shown.bs.modal', function () {
+                $('#modal-volume-edit-form-description').focus();
+            })
+
+            // Delete existing volumes
+            $('body').on( 'click', '.volume-delete', function(){
+                const volume_id = $(this).data('volume-id');
+                $('#modal-volume-delete-submit').data('volume-id', volume_id );
+                $('#modal-volume-delete-submit').removeAttr('disabled');
+                $('#modal-volume-delete').modal('show');
+            });
+            $("#modal-volume-delete-submit").on('click', function(){
+                $('#modal-volume-delete-submit').attr('disabled', 'disabled');
+                const volume_id = $("#modal-volume-delete-submit").data('volume-id');
+
+                $.ajax({
+                    url: `/api/v1/biblios/${biblionumber}/volumes/${volume_id}`,
+                    headers: { "x-koha-embed": "items" },
+                    success: function(volume_data){
+                        $.ajax({
+                          "url": `/api/v1/biblios/${biblionumber}/volumes/${volume_id}`,
+                          "method": "DELETE",
+                        })
+                        .done(function (response) {
+                            $('#modal-volume-delete').modal('hide');
+                            $(`#volume-add-form-select option[value='${volume_id}']`).remove();
+                            if ( volume_data.items === null ) {
+                                // No items for this volume, we can just refresh the table
+                                volumesTable.api().ajax.reload();
+                            } else {
+                                // This volume had items attached to it, we need to reload the page
+                                window.location.replace(`/cgi-bin/koha/catalogue/detail.pl?biblionumber=${biblionumber}`);
+                            }
+                        })
+                        .fail(function(err) {
+                            var message = err.responseJSON.error;
+                            alert(message);
+                        });
+                    }
+                });
+            });
+        [% END %]
     </script>
 [% END %]
 [% INCLUDE 'intranet-bottom.inc' %]
-- 
2.11.0