From cfbe19316772b30a589b08cf0b2f3ed1b60fddfc Mon Sep 17 00:00:00 2001 From: Kyle M Hall Date: Mon, 9 Feb 2015 07:30:35 -0500 Subject: [PATCH] Bug 13733 - Give librarians the ability to add messages to an item Some librarians would like the ability to leave messages attached to an item ( outside the scope of itemnotes and itemnotes_nonpublic ). This feature would give the librarians the ability to add and remove messages of arbitrary types defined in an authorised value list. Test Plan: 1) Apply this patch set 2) Run updatedatabase.pl 3) Create some ITEM_MESSAGE authorised values 4) View an item's details 5) Try adding and deleting messages on an item --- Koha/Schema/Result/ItemMessage.pm | 111 +++++++++++++ Koha/Service/AuthorisedValues.pm | 63 ++++++++ Koha/Service/Item/Message.pm | 162 ++++++++++++++++++++ .../intranet-tmpl/prog/en/js/item-messages.js | 89 +++++++++++ .../prog/en/modules/catalogue/moredetail.tt | 9 +- svc/authorised_values | 24 +++ svc/item/message | 24 +++ 7 files changed, 481 insertions(+), 1 deletions(-) create mode 100644 Koha/Schema/Result/ItemMessage.pm create mode 100644 Koha/Service/AuthorisedValues.pm create mode 100644 Koha/Service/Item/Message.pm create mode 100644 koha-tmpl/intranet-tmpl/prog/en/js/item-messages.js create mode 100755 svc/authorised_values create mode 100755 svc/item/message diff --git a/Koha/Schema/Result/ItemMessage.pm b/Koha/Schema/Result/ItemMessage.pm new file mode 100644 index 0000000..a08769a --- /dev/null +++ b/Koha/Schema/Result/ItemMessage.pm @@ -0,0 +1,111 @@ +use utf8; +package Koha::Schema::Result::ItemMessage; + +# Created by DBIx::Class::Schema::Loader +# DO NOT MODIFY THE FIRST PART OF THIS FILE + +=head1 NAME + +Koha::Schema::Result::ItemMessage + +=cut + +use strict; +use warnings; + +use base 'DBIx::Class::Core'; + +=head1 TABLE: C + +=cut + +__PACKAGE__->table("item_messages"); + +=head1 ACCESSORS + +=head2 item_message_id + + data_type: 'integer' + is_auto_increment: 1 + is_nullable: 0 + +=head2 itemnumber + + data_type: 'integer' + is_foreign_key: 1 + is_nullable: 0 + +=head2 type + + data_type: 'varchar' + is_nullable: 1 + size: 80 + +=head2 message + + data_type: 'text' + is_nullable: 0 + +=head2 created_on + + data_type: 'timestamp' + datetime_undef_if_invalid: 1 + default_value: current_timestamp + is_nullable: 0 + +=cut + +__PACKAGE__->add_columns( + "item_message_id", + { data_type => "integer", is_auto_increment => 1, is_nullable => 0 }, + "itemnumber", + { data_type => "integer", is_foreign_key => 1, is_nullable => 0 }, + "type", + { data_type => "varchar", is_nullable => 1, size => 80 }, + "message", + { data_type => "text", is_nullable => 0 }, + "created_on", + { + data_type => "timestamp", + datetime_undef_if_invalid => 1, + default_value => \"current_timestamp", + is_nullable => 0, + }, +); + +=head1 PRIMARY KEY + +=over 4 + +=item * L + +=back + +=cut + +__PACKAGE__->set_primary_key("item_message_id"); + +=head1 RELATIONS + +=head2 itemnumber + +Type: belongs_to + +Related object: L + +=cut + +__PACKAGE__->belongs_to( + "itemnumber", + "Koha::Schema::Result::Item", + { itemnumber => "itemnumber" }, + { is_deferrable => 1, on_delete => "CASCADE", on_update => "CASCADE" }, +); + + +# Created by DBIx::Class::Schema::Loader v0.07040 @ 2015-02-09 07:59:08 +# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:6shNRfWMQ+v1d5GwgX01rw + + +# You can replace this text with custom code or comments, and it will be preserved on regeneration +1; diff --git a/Koha/Service/AuthorisedValues.pm b/Koha/Service/AuthorisedValues.pm new file mode 100644 index 0000000..6c7c9f1 --- /dev/null +++ b/Koha/Service/AuthorisedValues.pm @@ -0,0 +1,63 @@ +package Koha::Service::AuthorisedValues; + +# This file is part of Koha. +# +# Copyright (C) 2015 ByWater Solutions +# +# 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 JSON; + +use C4::Koha; + +use base 'Koha::Service'; + +sub new { + my ($class) = @_; + + # Authentication is handled manually below + return $class->SUPER::new( + { + authnotrequired => 0, + routes => [ + [ qr'GET /(.+)', 'get_authorised_values' ], + ], + } + ); +} + +sub run { + my ($self) = @_; + + $self->authenticate; + + unless ( $self->auth_status eq "ok" ) { + $self->output( + XMLout( { auth_status => $self->auth_status }, NoAttr => 1, RootName => 'response', XMLDecl => 1 ), + { type => 'xml', status => '403 Forbidden' } ); + exit; + } + + $self->dispatch; +} + +sub get_authorised_values { + my ( $self, $category ) = @_; + + $self->output( GetAuthorisedValues($category) ); +} + +1; diff --git a/Koha/Service/Item/Message.pm b/Koha/Service/Item/Message.pm new file mode 100644 index 0000000..93a6d4f --- /dev/null +++ b/Koha/Service/Item/Message.pm @@ -0,0 +1,162 @@ +package Koha::Service::Item::Message; + +# This file is part of Koha. +# +# Copyright (C) 2015 ByWater Solutions +# +# 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 JSON; + +use Koha::Database; +use C4::Koha; + +use base 'Koha::Service'; + +sub new { + my ($class) = @_; + + # Authentication is handled manually below + return $class->SUPER::new( + { + authnotrequired => 0, + needed_flags => { editcatalogue => 'edit_catalogue' }, + routes => [ + [ qr'GET /(\d+)', 'get_messages' ], + [ qr'POST /(\d+)', 'add_message' ], + [ qr'PUT /(\d+)', 'update_message' ], + [ qr'DELETE /(\d+)', 'delete_message' ], + ] + } + ); +} + +sub run { + my ($self) = @_; + + $self->authenticate; + + unless ( $self->auth_status eq "ok" ) { + $self->output( + XMLout( { auth_status => $self->auth_status }, NoAttr => 1, RootName => 'response', XMLDecl => 1 ), + { type => 'xml', status => '403 Forbidden' } ); + exit; + } + + $self->dispatch; +} + +sub get_messages { + my ( $self, $itemnumber ) = @_; + + my $rs = Koha::Database->new->schema()->resultset('ItemMessage') + ->search( { itemnumber => $itemnumber }, { result_class => 'DBIx::Class::ResultClass::HashRefInflator' } ); + + my @messages = map { $_ } $rs->all(); + map { $_->{authorised_value} = GetAuthorisedValueByCode( 'ITEM_MESSAGE', $_->{type} ) } @messages; + + warn Data::Dumper::Dumper( \@messages ); + + $self->output( \@messages ); +} + +sub add_message { + my ( $self, $itemnumber ) = @_; + + my $query = $self->query; + + my $json = $query->param('POSTDATA'); + my $data = from_json( $json, { utf8 => 1 } ); + + my $type = $data->{type}; + my $message = $data->{message}; + + my $msg = Koha::Database->new->schema()->resultset('ItemMessage')->create( + { + itemnumber => $itemnumber, + type => $type, + message => $message, + } + ); + $msg->discard_changes(); + + $self->output( + { + item_message_id => $msg->id(), + itemnumber => $itemnumber, + type => $type, + message => $message, + created_on => $msg->created_on(), + authorised_value => GetAuthorisedValueByCode( 'ITEM_MESSAGE', $type ), + } + ); +} + +sub update_message { + my ( $self, $id ) = @_; + + my $query = $self->query; + + my $json = $query->param('PUTDATA'); + my $data = from_json( $json, { utf8 => 1 } ); + + my $type = $data->{type}; + my $message = $data->{message}; + + my $msg = Koha::Database->new->schema()->resultset('ItemMessage')->find($id); + + craok("no item message") unless $msg; + + $msg->update( + { + type => $type, + message => $message, + } + ); + + $self->output( + { + item_message_id => $msg->id(), + itemnumber => $msg->get_column('itemnumber'), + type => $type, + message => $message, + created_on => $msg->created_on(), + authorised_value => GetAuthorisedValueByCode( 'ITEM_MESSAGE', $type ), + } + ); +} + +sub delete_message { + my ( $self, $id ) = @_; + + my $msg = Koha::Database->new->schema()->resultset('ItemMessage')->find($id); + + craok("no item message") unless $msg; + + $msg->delete(); + + $self->output( + { + item_message_id => $msg->id(), + itemnumber => $msg->get_column('itemnumber'), + type => $msg->type(), + message => $msg->message(), + created_on => $msg->created_on(), + } + ); +} + +1; diff --git a/koha-tmpl/intranet-tmpl/prog/en/js/item-messages.js b/koha-tmpl/intranet-tmpl/prog/en/js/item-messages.js new file mode 100644 index 0000000..aa73c26 --- /dev/null +++ b/koha-tmpl/intranet-tmpl/prog/en/js/item-messages.js @@ -0,0 +1,89 @@ +var koha = angular.module('Koha', []); + +koha.factory('AuthorisedValueService', [ '$http', function( $http ) { + var authorised_values = {}; + + return { + list: function( params ) { + var category = params.category; + var callback = params.callback; + + if ( authorised_values[category] ) { + if ( callback ) { + return callback(authorised_values[category]); + } else { + return authorised_values[category]; + } + } else { + $http.get('/cgi-bin/koha/svc/authorised_values/' + category).then(function(response) { + authorised_values[category] = response.data; + + if ( callback ) { + return callback(response.data); + } else { + return response.data; + } + }, function(errResponse) { + console.error('Error while fetching authorised values'); + }); + } + }, + }; +}]); + +koha.directive('itemMessages', [ '$http', 'AuthorisedValueService', function( $http, AuthorisedValueService ) { + return { + scope: { + itemnumber: '@' + }, + templateUrl: '/intranet-tmpl/prog/en/includes/partials/widgets/item-messages.html', + link: function($scope, $element, $attrs) { + $scope.showAddNewMessage = false; + $scope.messages = []; + + AuthorisedValueService.list( { + category: 'ITEM_MESSAGE', + callback: function( types ) { + $scope.types = types; + }, + } ); + + $http.get('/cgi-bin/koha/svc/item/message/' + $scope.itemnumber).then(function(response) { + $scope.messages = response.data; + }, function(errResponse) { + console.error('Error while fetching notes'); + }); + + $scope.create = function() { + $scope.showAddNewMessage = false; + + $http.post('/cgi-bin/koha/svc/item/message/' + $scope.itemnumber, $scope.itemMessage).then(function(response) { + $scope.hideNewMessageEditor(); + $scope.messages.push( response.data ); + }, function(errResponse) { + console.error('Error while posting note'); + }); + } + + $scope.remove = function(im) { + $http.delete('/cgi-bin/koha/svc/item/message/' + im.item_message_id).then(function(response) { + var index = $scope.messages.indexOf(im); + $scope.messages.splice( index, 1 ); + }, function(errResponse) { + console.error('Error while deleting note'); + }); + } + + $scope.showNewMessageEditor = function() { + $scope.showAddNewMessage = true; + }; + + $scope.hideNewMessageEditor = function() { + $scope.showAddNewMessage = false; + $scope.itemMessage.type = ""; + $scope.itemMessage.message = ""; + }; + } + }; +}]); + diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/catalogue/moredetail.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/catalogue/moredetail.tt index 1ddc952..2e808d6 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/catalogue/moredetail.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/catalogue/moredetail.tt @@ -13,8 +13,10 @@ browser.show(); //]]> +[% INCLUDE 'doc-head-angular.inc' %] + - + [% USE KohaDates %] [% INCLUDE 'header.inc' %] [% INCLUDE 'cat-search.inc' %] @@ -181,6 +183,11 @@ [% IF ITEM_DAT.withdrawn_on %]
  • Withdrawn on:[% ITEM_DAT.withdrawn_on | $KohaDates %]  
  • [% END %] + +
    + +
    +

    History

      diff --git a/svc/authorised_values b/svc/authorised_values new file mode 100755 index 0000000..4916241 --- /dev/null +++ b/svc/authorised_values @@ -0,0 +1,24 @@ +#!/usr/bin/perl + +# Copyright (C) 2015 ByWater Solutions +# +# 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 2 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, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# + +use Modern::Perl; + +use Koha::Service::AuthorisedValues; +Koha::Service::AuthorisedValues->new->run; diff --git a/svc/item/message b/svc/item/message new file mode 100755 index 0000000..44be7f7 --- /dev/null +++ b/svc/item/message @@ -0,0 +1,24 @@ +#!/usr/bin/perl + +# Copyright (C) 2015 ByWater Solutions +# +# 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 2 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, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# + +use Modern::Perl; + +use Koha::Service::Item::Message; +Koha::Service::Item::Message->new->run; -- 1.7.2.5