Bug 31028: Add display to details page
authorMartin Renvoize <martin.renvoize@ptfs-europe.com>
Tue, 25 Oct 2022 15:02:09 +0000 (16:02 +0100)
committerTomas Cohen Arazi <tomascohen@theke.io>
Mon, 6 Mar 2023 14:23:17 +0000 (11:23 -0300)
This patch adds the display of biblio specific concerns to the biblio
detail display page.

Test plan
1) Enable the feature as in prior patch test plans
2) Add a concern as per prior patch test plans
3) Confirm that a new tab appears at the bottom of the catalog record
   details display and all functionality from the concern management
   page is precent.

Signed-off-by: David Nind <david@davidnind.com>
Signed-off-by: Helen Oliver <HOliver@tavi-port.ac.uk>
Signed-off-by: Kyle M Hall <kyle@bywatersolutions.com>
Signed-off-by: Tomas Cohen Arazi <tomascohen@theke.io>
koha-tmpl/intranet-tmpl/prog/en/includes/modals/display_ticket.inc [new file with mode: 0644]
koha-tmpl/intranet-tmpl/prog/en/modules/catalogue/detail.tt
koha-tmpl/intranet-tmpl/prog/en/modules/cataloguing/concerns.tt
koha-tmpl/intranet-tmpl/prog/en/modules/intranet-main.tt
koha-tmpl/intranet-tmpl/prog/js/modals/display_ticket.js [new file with mode: 0644]

diff --git a/koha-tmpl/intranet-tmpl/prog/en/includes/modals/display_ticket.inc b/koha-tmpl/intranet-tmpl/prog/en/includes/modals/display_ticket.inc
new file mode 100644 (file)
index 0000000..3bf471a
--- /dev/null
@@ -0,0 +1,31 @@
+<!-- Display updates concern modal -->
+<div class="modal" id="ticketDetailsModal" tabindex="-1" role="dialog" aria-labelledby="ticketDetailsLabel">
+    <div class="modal-dialog modal-lg" 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="displayUpdateLabel">Ticket details</h4>
+            </div>
+            <div class="modal-body">
+                <div id="concern-details"></div>
+                <fieldset>
+                    <ol>
+                        <li class="form-group">
+                            <label for="message">Update: </label>
+                            <textarea id="update_message" class="form-control" name="message"></textarea>
+                        </li>
+                        <li class="rows">
+                            <label for="public">Notify: </label>
+                            <input type="checkbox" name="public" id="public">
+                        </li>
+                    </ol>
+                </fieldset>
+            </div> <!-- /.modal-body -->
+            <div class="modal-footer">
+                <input type="hidden" name="ticket_id" id="ticket_id">
+                <button type="button" class="btn btn-default" id="resolveTicket">Resolve <i id="resolve-spinner" class="fa fa-spinner fa-pulse fa-fw" style="display:none"></i></button>
+                <button type="submit" class="btn btn-primary" id="updateTicket">Comment <i id="comment-spinner" class="fa fa-spinner fa-pulse fa-fw" style="display:none"></i></button>
+            </div> <!-- /.modal-footer -->
+        </div> <!-- /.modal-content -->
+    </div> <!-- /.modal-dialog -->
+</div> <!-- /#displayUpdateModal -->
index 713b45b..6aa948a 100644 (file)
 [% IF Koha.Preference('AcquisitionDetails') %]<li role="presentation"><a href="#acq_details"  aria-controls="acq_details" role="tab" data-toggle="tab">Acquisition details</a></li>[% END %]
 [% IF suggestions.count %]<li role="presentation"><a href="#suggestion_details"  aria-controls="suggestion_details" role="tab" data-toggle="tab">Suggestion details</a></li>[% END %]
 [% IF ( FRBRizeEditions ) %][% IF ( XISBNS ) %]<li role="presentation"><a href="#editions"  aria-controls="editions" role="tab" data-toggle="tab">Editions</a></li>[% END %][% END %]
+[% IF ( ( Koha.Preference('CatalogConcerns') || Koha.Preference('OpacCatalogConcerns') ) && CAN_user_editcatalogue_edit_catalogue ) %]<li role="presentation"><a href="#concerns" aria-controls="concerns" role="tab" data-toggle="tab">Concerns ([% biblio.tickets.count | html %])</a></li>[% END %]
 [% IF ( LocalCoverImages ) %]
     <li role="presentation">
         <a href="#images"  aria-controls="images" role="tab" data-toggle="tab">Images ([% localimages.count || 0 | html %])</a>
@@ -1007,6 +1008,26 @@ Note that permanent location is a code, and location may be an authval.
 </table></div>[% END %]
 [% END %]
 
+[% IF ( ( Koha.Preference('CatalogConcerns') || Koha.Preference('OpacCatalogConcerns') ) && CAN_user_editcatalogue_edit_catalogue ) %]
+<div role="tabpanel" class="tab-pane" id="concerns">
+    <fieldset class="action" style="cursor:pointer;">
+        <a id="hideResolved"><i class="fa fa-minus-square"></i> Hide resolved</a>
+        | <a id="showAll"><i class="fa fa-bars"></i> Show all</a>
+    </fieldset>
+
+    <table id="table_concerns" width="100%">
+        <thead>
+            <tr>
+                <th>Reported</th>
+                <th>Details</th>
+                <th>Status</th>
+                <th data-class-name="actions noExport">Actions</th>
+            </tr>
+        </thead>
+    </table>
+</div>
+[% END %]
+
 [% IF ( LocalCoverImages ) %]
     <div role="tabpanel" class="tab-pane" id="images">
         [% IF localimages.count %]
@@ -1310,6 +1331,10 @@ Note that permanent location is a code, and location may be an authval.
     [% INCLUDE 'modals/add_catalog_concern.inc' %]
     [% END %]
 
+    [% IF ( ( Koha.Preference('CatalogConcerns') || Koha.Preference('OpacCatalogConcerns') ) && CAN_user_editcatalogue_edit_catalogue ) %]
+    [% INCLUDE 'modals/display_ticket.inc' %]
+    [% END %]
+
 [% MACRO jsinclude BLOCK %]
     [% INCLUDE 'catalog-strings.inc' %]
     [% Asset.js("js/catalog.js") | $raw %]
@@ -1322,6 +1347,106 @@ Note that permanent location is a code, and location may be an authval.
             var logged_in_user_borrowernumber = "[% logged_in_user.borrowernumber | html %]";
         </script>
         [% Asset.js("js/modals/add_catalog_concern.js") | $raw %]
+     [% END %]
+     [% IF ( ( Koha.Preference('CatalogConcerns') || Koha.Preference('OpacCatalogConcerns') ) && CAN_user_editcatalogue_edit_catalogue ) %]
+         <script>
+            $(document).ready(function() {
+                var table_settings = [% TablesSettings.GetTableSettings( 'cataloguing', 'concerns', 'table_concerns', 'json' ) | $raw %];
+
+                var tickets_url = '/api/v1/tickets';
+                var tickets = $("#table_concerns").kohaTable({
+                    "ajax": {
+                        "url": tickets_url
+                    },
+                    "embed": [
+                        "reporter",
+                        "resolver",
+                        "updates+count",
+                    ],
+                    'emptyTable': '<div class="dialog message">' + _("Congratulations, there are no catalog concerns.") + '</div>',
+                    "columnDefs": [ {
+                        "targets": [0,1,2],
+                        "render": function (data, type, row, meta) {
+                            if ( type == 'display' ) {
+                                if ( data != null ) {
+                                    return data.escapeHtml();
+                                }
+                                else {
+                                    return "";
+                                }
+                            }
+                            return data;
+                        }
+                    } ],
+                    "columns": [
+                        {
+                            "data": "reported_date:reporter.firstname",
+                            "render": function(data, type, row, meta) {
+                                let reported = '<span class="date clearfix">' + $datetime(row.reported_date) + '</span>';
+                                reported += '<span class="reporter clearfix">' + $patron_to_html(row.reporter, {
+                                    display_cardnumber: false,
+                                    url: true
+                                }) + '</span>';
+                                return reported;
+                            },
+                            "searchable": true,
+                            "orderable": true
+                        },
+                        {
+                            "data": "title:body",
+                            "render": function(data, type, row, meta) {
+                                let resolved = ( row.resolved_date ) ? true : false;
+                                let result = '<a role="button" href="#" data-toggle="modal" data-target="#ticketDetailsModal" data-concern="' + encodeURIComponent(row.ticket_id) + '" data-resolved="' + resolved + '">' + row.title + '</a>';
+                                if (row.updates_count) {
+                                    result += '<span class="pull-right"><a role="button" href="#" data-toggle="modal" data-target="#ticketDetailsModal" data-concern="' + encodeURIComponent(row.ticket_id) + '"><i class="fa fa-comment" aria-hidden="true"></i> ' + row.updates_count + '</a></span>';
+                                }
+                                result += '<div id="detail_' + row.ticket_id + '" class="hidden">' + row.body + '</div>';
+                                return result;
+                            },
+                            "searchable": true,
+                            "orderable": true
+                        },
+                        {
+                            "data": "resolved_date",
+                            "render": function(data, type, row, meta) {
+                                let result = '';
+                                if (row.resolved_date) {
+                                    result += _("Resolved by:") + ' <span>' + $patron_to_html(row.resolver, {
+                                        display_cardnumber: false,
+                                        url: true
+                                    }) + '</span>';
+                                    result += '<span class="clearfix">' + $datetime(row.resolved_date) + '</span>';
+                                } else {
+                                    result += _("Open");
+                                }
+                                return result;
+                            },
+                            "searchable": true,
+                            "orderable": true
+                        },
+                        {
+                            "data": function(row, type, val, meta) {
+                                let resolved = ( row.resolved_date ) ? true : false;
+                                let result = '<a class="btn btn-default btn-xs" role="button" href="#" data-toggle="modal" data-target="#ticketDetailsModal" data-concern="' + encodeURIComponent(row.ticket_id) + '" data-resolved="' + resolved + '"><i class="fa fa-eye" aria-hidden="true"></i> ' + _("Details") + '</a>';
+                                return result;
+                            },
+                            "searchable": false,
+                            "orderable": false
+                        },
+                    ]
+                }, table_settings, 0, { biblio_id: [% biblionumber | uri %]});
+
+                $('#hideResolved').on( "click", function() {
+                    // It would be great if we could pass null here but it gets stringified
+                    concerns.DataTable().columns('3').search('special:undefined').draw();
+                });
+
+                $('#showAll').on( "click", function() {
+                    concerns.DataTable().columns('3').search('').draw();
+                });
+            });
+        </script>
+        [% Asset.js("js/modals/display_ticket.js") | $raw %]
     [% END %]
     <script>
         var interface = "[% interface | html %]";
index 7a87b95..0da6646 100644 (file)
             </div> <!-- /.col-sm-2.col-sm-pull-10 -->
         </div> <!-- /.row -->
 
-        <!-- Display updates concern modal -->
-        <div class="modal" id="ticketDetailsModal" tabindex="-1" role="dialog" aria-labelledby="ticketDetailsLabel">
-            <div class="modal-dialog modal-lg" 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="displayUpdateLabel">Ticket details</h4>
-                    </div>
-                    <div class="modal-body">
-                        <div id="concern-details"></div>
-                        <fieldset class="rows">
-                            <ol>
-                                <li>
-                                    <label for="message">Update: </label>
-                                    <textarea id="update_message" name="message"></textarea>
-                                </li>
-                                <li>
-                                    <label for="public">Notify: </label>
-                                    <input type="checkbox" name="public" id="public">
-                                </li>
-                            </ol>
-                        </fieldset>
-                    </div> <!-- /.modal-body -->
-                    <div class="modal-footer">
-                        <input type="hidden" name="ticket_id" id="ticket_id">
-                        <button type="button" class="btn btn-default" id="resolveTicket">Resolve</button>
-                        <button type="submit" class="btn btn-primary" id="updateTicket">Comment</button>
-                    </div> <!-- /.modal-footer -->
-                </div> <!-- /.modal-content -->
-            </div> <!-- /.modal-dialog -->
-        </div> <!-- /#displayUpdateModal -->
+        [% INCLUDE 'modals/display_ticket.inc' %]
 
 [% MACRO jsinclude BLOCK %]
     [% INCLUDE 'datatables.inc' %]
     <script>
         $(document).ready(function() {
 
-            var logged_in_user_borrowernumber = "[% logged_in_user.borrowernumber | html %]";
+            logged_in_user_borrowernumber = [% logged_in_user.borrowernumber | html %];
 
             var table_settings = [% TablesSettings.GetTableSettings('cataloguing', 'concerns', 'table_concerns', 'json') | $raw %];
 
                     {
                         "data": "title:body",
                         "render": function(data, type, row, meta) {
-                            let result = '<a role="button" href="#" data-toggle="modal" data-target="#ticketDetailsModal" data-concern="' + encodeURIComponent(row.ticket_id) + '">' + row.title + '</a>';
+                            let resolved = ( row.resolved_date ) ? true : false;
+                            let result = '<a role="button" href="#" data-toggle="modal" data-target="#ticketDetailsModal" data-concern="' + encodeURIComponent(row.ticket_id) + '" data-resolved="'+resolved+'">' + row.title + '</a>';
                             if (row.updates_count) {
-                                result += '<span class="pull-right"><a role="button" href="#" data-toggle="modal" data-target="#ticketDetailsModal" data-concern="' + encodeURIComponent(row.ticket_id) + '"><i class="fa fa-comment" aria-hidden="true"></i> ' + row.updates_count + '</a></span>';
+                                result += '<span class="pull-right"><a role="button" href="#" data-toggle="modal" data-target="#ticketDetailsModal" data-concern="' + encodeURIComponent(row.ticket_id) + '" data-resolved="'+resolved+'"><i class="fa fa-comment" aria-hidden="true"></i> ' + row.updates_count + '</a></span>';
                             }
                             result += '<div id="detail_' + row.ticket_id + '" class="hidden">' + row.body + '</div>';
                             return result;
                     },
                     {
                         "data": function(row, type, val, meta) {
-                            let result = '<a class="btn btn-default btn-xs" role="button" href="#" data-toggle="modal" data-target="#ticketDetailsModal" data-concern="' + encodeURIComponent(row.ticket_id) + '"><i class="fa fa-eye" aria-hidden="true"></i> ' + _("Details") + '</a>';
+                            let resolved = ( row.resolved_date ) ? true : false;
+                            let result = '<a class="btn btn-default btn-xs" role="button" href="#" data-toggle="modal" data-target="#ticketDetailsModal" data-concern="' + encodeURIComponent(row.ticket_id) + '" data-resolved="'+resolved+'"><i class="fa fa-eye" aria-hidden="true"></i> ' + _("Details") + '</a>';
                             return result;
                         },
                         "searchable": false,
             $('#showAll').on("click", function() {
                 tickets.DataTable().columns('3').search('').draw();
             });
-
-            $('#ticketDetailsModal').on('show.bs.modal', function(event) {
-                let modal = $(this);
-                let button = $(event.relatedTarget);
-                let ticket_id = button.data('concern');
-                modal.find('.modal-footer input').val(ticket_id);
-
-                let detail = $('#detail_' + ticket_id).text();
-
-                let display = '<div class="list-group">';
-                display += '<div class="list-group-item">';
-                display += '<span class="wrapfix">' + detail + '</span>';
-                display += '</div>';
-                display += '<div id="concern-updates" class="list-group-item">';
-                display += '<span>Loading updates . . .</span>';
-                display += '</div>';
-                display += '</div>';
-
-                let details = modal.find('#concern-details');
-                details.html(display);
-
-                $.ajax({
-                    url: "/api/v1/tickets/" + ticket_id + "/updates",
-                    method: "GET",
-                    headers: {
-                        "x-koha-embed": "user"
-                    },
-                }).success(function(data) {
-                    let updates_display = $('#concern-updates');
-                    let updates = '';
-                    data.forEach(function(item, index) {
-                        updates += '<div class="list-group-item">';
-                        updates += '<span class="wrapfix">' + item.message + '</span>';
-                        updates += '<span class="clearfix">' + $patron_to_html(item.user, {
-                            display_cardnumber: false,
-                            url: true
-                        }) + ' (' + $datetime(item.date) + ')</span>';
-                        updates += '</div>';
-                    });
-                    updates_display.html(updates);
-                }).error(function() {
-
-                });
-            });
-
-            $('#ticketDetailsModal').on('click', '#updateTicket', function(e) {
-                let ticket_id = $('#ticket_id').val();
-                let params = {
-                    'public': $('#public').is(":checked"),
-                    message: $('#update_message').val(),
-                    user_id: logged_in_user_borrowernumber
-                };
-
-                $.ajax({
-                    url: "/api/v1/tickets/" + ticket_id + "/updates",
-                    method: "POST",
-                    data: JSON.stringify(params),
-                    ontentType: "application/json; charset=utf-8"
-                }).success(function() {
-                    $("#ticketDetailsModal").modal('hide');
-                    tickets.DataTable().ajax.reload(function(data) {
-                        $("#concern_action_result_dialog").hide();
-                        $("#concern_delete_success").html(_("Concern #%s updated successfully.").format(ticket_id)).show();
-                    });
-                }).error(function() {
-                    $("#concern_update_error").html(_("Error resolving concern #%s. Check the logs.").format(ticket_id)).show();
-                });
-            });
-
-            $('#ticketDetailsModal').on('click', '#resolveTicket', function(e) {
-                let ticket_id = $('#ticket_id').val();
-                let params = {
-                    'public': $('#public').is(":checked"),
-                    message: $('#update_message').val(),
-                    user_id: logged_in_user_borrowernumber,
-                    state: 'resolved'
-                };
-
-                $.ajax({
-                    url: "/api/v1/tickets/" + ticket_id + "/updates",
-                    method: "POST",
-                    data: JSON.stringify(params),
-                    ontentType: "application/json; charset=utf-8"
-                }).success(function() {
-                    $("#ticketDetailsModal").modal('hide');
-                    tickets.DataTable().ajax.reload(function(data) {
-                        $("#concern_action_result_dialog").hide();
-                        $("#concern_delete_success").html(_("Concern #%s updated successfully.").format(ticket_id)).show();
-                    });
-                }).error(function() {
-                    $("#concern_update_error").html(_("Error resolving concern #%s. Check the logs.").format(ticket_id)).show();
-                });
-            });
-
         });
     </script>
+    [% Asset.js("js/modals/display_ticket.js") | $raw %]
 [% END %]
 [% INCLUDE 'intranet-bottom.inc' %]
index 3960236..f60d4d4 100644 (file)
                 <div class="row">
                     <div class="col-sm-12">
                         [%# Following statement must be in one line for translatability %]
-                        [% IF ( CAN_user_tools_moderate_comments  && pendingcomments ) || ( CAN_user_tools_moderate_tags && pendingtags ) || ( CAN_user_borrowers_edit_borrowers && pending_borrower_modifications ) || ( CAN_user_suggestions_suggestions_manage && ( pendingsuggestions || all_pendingsuggestions )) || ( CAN_user_borrowers_edit_borrowers && pending_discharge_requests ) || pending_article_requests || ( Koha.Preference('AllowCheckoutNotes') && CAN_user_circulate_manage_checkout_notes && pending_checkout_notes.count ) || ( ( Koha.preference('OpacCatalogConcerns') || Koha.Preference('CatalogConcerns') ) && pending_biblio_tickets && CAN_user_editcatalogue_edit_catalogue ) || ( Koha.Preference('OPACReportProblem') && CAN_user_problem_reports && pending_problem_reports.count ) || already_ran_jobs || new_curbside_pickups.count %]
+                        [% IF ( CAN_user_tools_moderate_comments  && pendingcomments ) || ( CAN_user_tools_moderate_tags && pendingtags ) || ( CAN_user_borrowers_edit_borrowers && pending_borrower_modifications ) || ( CAN_user_suggestions_suggestions_manage && ( pendingsuggestions || all_pendingsuggestions )) || ( CAN_user_borrowers_edit_borrowers && pending_discharge_requests ) || pending_article_requests || ( Koha.Preference('AllowCheckoutNotes') && CAN_user_circulate_manage_checkout_notes && pending_checkout_notes.count ) || ( ( Koha.Preference('OpacCatalogConcerns') || Koha.Preference('CatalogConcerns') ) && pending_biblio_tickets && CAN_user_editcatalogue_edit_catalogue ) || ( Koha.Preference('OPACReportProblem') && CAN_user_problem_reports && pending_problem_reports.count ) || already_ran_jobs || new_curbside_pickups.count %]
                             <div id="area-pending" class="page-section">
                                 [% IF pending_article_requests %]
                                 <div class="pending-info" id="article_requests_pending">
diff --git a/koha-tmpl/intranet-tmpl/prog/js/modals/display_ticket.js b/koha-tmpl/intranet-tmpl/prog/js/modals/display_ticket.js
new file mode 100644 (file)
index 0000000..653f3f9
--- /dev/null
@@ -0,0 +1,120 @@
+$(document).ready(function() {
+    $('#ticketDetailsModal').on('show.bs.modal', function(event) {
+        let modal = $(this);
+        let button = $(event.relatedTarget);
+        let ticket_id = button.data('concern');
+        let resolved  = button.data('resolved');
+        modal.find('.modal-footer input').val(ticket_id);
+
+        if ( resolved ) {
+            $('#resolveTicket').hide();
+        } else {
+            $('#resolveTicket').show();
+        }
+
+        let detail = $('#detail_' + ticket_id).text();
+
+        // Display ticket details
+        let display = '<div class="list-group">';
+        display += '<div class="list-group-item">';
+        display += '<span class="wrapfix">' + detail + '</span>';
+        display += '</div>';
+        display += '<div id="concern-updates" class="list-group-item">';
+        display += '<span>' + __("Loading updates . . .") + '</span>';
+        display += '</div>';
+        display += '</div>';
+
+        let details = modal.find('#concern-details');
+        details.html(display);
+
+        // Load any existing updates
+        $.ajax({
+            url: "/api/v1/tickets/" + ticket_id + "/updates",
+            method: "GET",
+            headers: {
+                "x-koha-embed": "user"
+            },
+        }).success(function(data) {
+            let updates_display = $('#concern-updates');
+            let updates = '';
+            data.forEach(function(item, index) {
+                if ( item.public ) {
+                    updates += '<div class="list-group-item list-group-item-success">';
+                    updates += '<span class="pull-right">' + __("Public") + '</span>';
+                }
+                else {
+                    updates += '<div class="list-group-item list-group-item-warning">';
+                    updates += '<span class="pull-right">' + __("Private") + '</span>';
+                }
+                updates += '<span class="wrapfix">' + item.message + '</span>';
+                updates += '<span class="clearfix">' + $patron_to_html(item.user, {
+                    display_cardnumber: false,
+                    url: true
+                }) + ' (' + $datetime(item.date) + ')</span>';
+                updates += '</div>';
+            });
+            updates_display.html(updates);
+        }).error(function() {
+
+        });
+
+        // Clear any previously entered update message
+        $('#update_message').val('');
+        $('#public').prop( "checked", false );
+    });
+
+    $('#ticketDetailsModal').on('click', '#updateTicket', function(e) {
+        let ticket_id = $('#ticket_id').val();
+        let params = {
+            'public': $('#public').is(":checked"),
+            message: $('#update_message').val(),
+            user_id: logged_in_user_borrowernumber
+        };
+
+        $('#comment-spinner').show();
+
+        $.ajax({
+            url: "/api/v1/tickets/" + ticket_id + "/updates",
+            method: "POST",
+            data: JSON.stringify(params),
+            ontentType: "application/json; charset=utf-8"
+        }).success(function() {
+            $('#comment-spinner').hide();
+            $('#ticketDetailsModal').modal('hide');
+            $('#table_concerns').DataTable().ajax.reload(function(data) {
+                $("#concern_action_result_dialog").hide();
+                $("#concern_delete_success").html(__("Concern #%s updated successfully.").format(ticket_id)).show();
+            });
+        }).error(function() {
+            $("#concern_update_error").html(__("Error resolving concern #%s. Check the logs.").format(ticket_id)).show();
+        });
+    });
+
+    $('#ticketDetailsModal').on('click', '#resolveTicket', function(e) {
+        let ticket_id = $('#ticket_id').val();
+        let params = {
+            'public': $('#public').is(":checked"),
+            message: $('#update_message').val(),
+            user_id: logged_in_user_borrowernumber,
+            state: 'resolved'
+        };
+
+        $('#resolve-spinner').show();
+
+        $.ajax({
+            url: "/api/v1/tickets/" + ticket_id + "/updates",
+            method: "POST",
+            data: JSON.stringify(params),
+            ontentType: "application/json; charset=utf-8"
+        }).success(function() {
+            $('#resolve-spinner').hide();
+            $("#ticketDetailsModal").modal('hide');
+            $('#table_concerns').DataTable().ajax.reload(function(data) {
+                $("#concern_action_result_dialog").hide();
+                $("#concern_delete_success").html(__("Concern #%s updated successfully.").format(ticket_id)).show();
+            });
+        }).error(function() {
+            $("#concern_update_error").html(__("Error resolving concern #%s. Check the logs.").format(ticket_id)).show();
+        });
+    });
+});