From 82145411141c29c6c4b8849a1ae11fefb65ceabc Mon Sep 17 00:00:00 2001 From: Jonathan Druart Date: Fri, 6 Sep 2013 10:27:04 +0200 Subject: [PATCH] Bug 9016: Create a message for each transport type. This patch adds: - a new jquery plugin : insertatcaret. - the ability to define a notice template for each transport type. - a new routine C4::Letters::GetMessageTransportTypes. Test plan: - Go on tools/letter.pl and check that all existing notices are still there. - Modify one. A new empty message is present for sms, print, etc. The email message is filled with the existant value. - Add a message for sms for example (don't forget the subject) and save. - edit again and verify the sms message has been saved. Signed-off-by: Olli-Antti Kivilahti Signed-off-by: Marcel de Rooy Signed-off-by: Galen Charlton --- C4/Letters.pm | 63 +++- .../jquery/plugins/jquery.insertatcaret.js | 46 +++ .../prog/en/modules/tools/letter.tt | 328 +++++++++--------- t/db_dependent/Letters.t | 13 +- tools/letter.pl | 163 ++++++--- 5 files changed, 377 insertions(+), 236 deletions(-) create mode 100644 koha-tmpl/intranet-tmpl/prog/en/lib/jquery/plugins/jquery.insertatcaret.js diff --git a/C4/Letters.pm b/C4/Letters.pm index 5025c10f62..8dbe3eda2f 100644 --- a/C4/Letters.pm +++ b/C4/Letters.pm @@ -43,7 +43,7 @@ BEGIN { $VERSION = 3.07.00.049; @ISA = qw(Exporter); @EXPORT = qw( - &GetLetters &GetPreparedLetter &GetWrappedLetter &addalert &getalert &delalert &findrelatedto &SendAlerts &GetPrintMessages + &GetLetters &GetPreparedLetter &GetWrappedLetter &addalert &getalert &delalert &findrelatedto &SendAlerts &GetPrintMessages &GetMessageTransportTypes ); } @@ -98,20 +98,19 @@ $template->param(LETTERLOOP => \@letterloop); sub GetLetters { # returns a reference to a hash of references to ALL letters... - my $cat = shift; + my ( $cat, $message_transport_type ) = @_; + $message_transport_type ||= 'email'; my %letters; my $dbh = C4::Context->dbh; my $sth; - if (defined $cat) { - my $query = "SELECT * FROM letter WHERE module = ? ORDER BY name"; - $sth = $dbh->prepare($query); - $sth->execute($cat); - } - else { - my $query = "SELECT * FROM letter ORDER BY name"; - $sth = $dbh->prepare($query); - $sth->execute; - } + my $query = q{ + SELECT * FROM letter WHERE + }; + $query .= q{ module = ? AND } if defined $cat; + $query .= q{ message_transport_type = ? ORDER BY name}; + $sth = $dbh->prepare($query); + $sth->execute((defined $cat ? $cat : ()), $message_transport_type); + while ( my $letter = $sth->fetchrow_hashref ) { $letters{ $letter->{'code'} } = $letter->{'name'}; } @@ -125,7 +124,8 @@ sub GetLetters { # short-term fix, our will work. our %letter; sub getletter { - my ( $module, $code, $branchcode ) = @_; + my ( $module, $code, $branchcode, $message_transport_type ) = @_; + $message_transport_type ||= 'email'; if ( C4::Context->preference('IndependentBranches') @@ -136,17 +136,22 @@ sub getletter { } $branchcode //= ''; - if ( my $l = $letter{$module}{$code}{$branchcode} ) { + if ( my $l = $letter{$module}{$code}{$branchcode}{$message_transport_type} ) { return { %$l }; # deep copy } my $dbh = C4::Context->dbh; - my $sth = $dbh->prepare("select * from letter where module=? and code=? and (branchcode = ? or branchcode = '') order by branchcode desc limit 1"); - $sth->execute( $module, $code, $branchcode ); + my $sth = $dbh->prepare(q{ + SELECT * + FROM letter + WHERE module=? AND code=? AND (branchcode = ? OR branchcode = '') AND message_transport_type = ? + ORDER BY branchcode DESC LIMIT 1 + }); + $sth->execute( $module, $code, $branchcode, $message_transport_type ); my $line = $sth->fetchrow_hashref or return; $line->{'content-type'} = 'text/html; charset="UTF-8"' if $line->{is_html}; - $letter{$module}{$code}{$branchcode} = $line; + $letter{$module}{$code}{$branchcode}{$message_transport_type} = $line; return { %$line }; } @@ -448,7 +453,7 @@ sub GetPreparedLetter { my $letter_code = $params{letter_code} or croak "No letter_code"; my $branchcode = $params{branchcode} || ''; - my $letter = getletter( $module, $letter_code, $branchcode ) + my $letter = getletter( $module, $letter_code, $branchcode, $params{message_transport_type} ) or warn( "No $module $letter_code letter"), return; @@ -842,6 +847,28 @@ ENDSQL return $sth->fetchall_arrayref({}); } +=head2 GetMessageTransportTypes + + my @mtt = GetMessageTransportTypes(); + + returns a list of hashes + +=cut + +sub GetMessageTransportTypes { + my $dbh = C4::Context->dbh(); + my $sth = $dbh->prepare(" + SELECT message_transport_type + FROM message_transport_types + ORDER BY message_transport_type + "); + $sth->execute; + my @mtts = map{ + $_->[0] + } @{ $sth->fetchall_arrayref() }; + return \@mtts; +} + =head2 _add_attachements named parameters: diff --git a/koha-tmpl/intranet-tmpl/prog/en/lib/jquery/plugins/jquery.insertatcaret.js b/koha-tmpl/intranet-tmpl/prog/en/lib/jquery/plugins/jquery.insertatcaret.js new file mode 100644 index 0000000000..408eb5d071 --- /dev/null +++ b/koha-tmpl/intranet-tmpl/prog/en/lib/jquery/plugins/jquery.insertatcaret.js @@ -0,0 +1,46 @@ +/*! + * jQuery insertAtCaret + * Allows inserting text where the caret is in a textarea + * Copyright (c) 2003-2010 phpMyAdmin devel team + * Version: 1.0 + * Developed by the phpMyAdmin devel team. Modified by Alex King and variaas + * http://alexking.org/blog/2003/06/02/inserting-at-the-cursor-using-javascript + * http://www.mail-archive.com/jquery-en@googlegroups.com/msg08708.html + * Licensed under the GPL license: + * http://www.gnu.org/licenses/gpl.html + */ +;(function($) { + +$.fn.insertAtCaret = function (myValue) { + + return this.each(function() { + + //IE support + if (document.selection) { + + this.focus(); + sel = document.selection.createRange(); + sel.text = myValue; + this.focus(); + + } else if (this.selectionStart || this.selectionStart == '0') { + + //MOZILLA / NETSCAPE support + var startPos = this.selectionStart; + var endPos = this.selectionEnd; + var scrollTop = this.scrollTop; + this.value = this.value.substring(0, startPos)+ myValue+ this.value.substring(endPos,this.value.length); + this.focus(); + this.selectionStart = startPos + myValue.length; + this.selectionEnd = startPos + myValue.length; + this.scrollTop = scrollTop; + + } else { + + this.value += myValue; + this.focus(); + } + }); +}; + +})(jQuery); diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/tools/letter.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/tools/letter.tt index 9203d9ec05..03a6e5a1dd 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/tools/letter.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/tools/letter.tt @@ -3,6 +3,7 @@ [% INCLUDE 'doc-head-close.inc' %] [% INCLUDE 'datatables.inc' %] + @@ -153,75 +145,72 @@ $(document).ready(function() { [% END %] [% END %] - -[% IF ( letter ) %] - - - - - - - - - - - - [% FOREACH lette IN letter %] - [% can_edit = lette.branchcode || !independant_branch %] - [% UNLESS ( loop.odd ) %] - - [% ELSE %] - - [% END %] - - - - - + + + + [% END %] + +
LibraryModuleCodeNameCopy notice  
[% IF ( lette.branchname ) %][% lette.branchname %][% ELSE %](All libraries)[% END %][% lette.module %][% lette.code %][% lette.name %] - [% IF !independant_branch || !lette.branchcode %] -
+ [% IF letter %] + + + + + + + + + + + + + + [% FOREACH lette IN letter %] + [% can_edit = lette.branchcode || !independant_branch %] + + + + + + - - - - [% END %] - -
LibraryModuleCodeNameCopy notice  
[% IF lette.branchname %][% lette.branchname %][% ELSE %](All libraries)[% END %][% lette.module %][% lette.code %][% lette.name %] + [% IF !independant_branch || !lette.branchcode %] + - + - [% IF independant_branch %] - - [% ELSE %] - [% select_for_copy %] - [% END %] + [% IF independant_branch %] + + [% ELSE %] + [% select_for_copy %] + [% END %] - - [% END %] - - [% IF can_edit %] - Edit - [% END %] - - [% IF !lette.protected && can_edit %] - Delete - [% END %] -
-[% ELSE %] -
- [% IF ( branchcode ) %] -

There are no notices for this library.

+ + [% END %] +
+ [% IF can_edit %] + Edit + [% END %] + + [% IF !lette.protected && can_edit %] + Delete + [% END %] +
[% ELSE %] -

There are no notices.

+
+ [% IF ( branchcode ) %] +

There are no notices for this library.

+ [% ELSE %] +

There are no notices.

+ [% END %] +
[% END %] - -[% END %] [% END %] [% IF ( add_form ) %]

[% IF ( modify ) %]Modify notice[% ELSE %]Add notice[% END %]

-
+ [% IF ( modify ) %] @@ -249,45 +238,45 @@ $(document).ready(function() { [% IF ( modify ) %][% END %] - [% IF ( catalogue ) %] - + [% IF ( module == "catalogue" ) %] + [% ELSE %] - + [% END %] - [% IF ( circulation ) %] - + [% IF ( module == "circulation" ) %] + [% ELSE %] - + [% END %] - [% IF ( claimacquisition ) %] - + [% IF ( module == "claimacquisition" ) %] + [% ELSE %] - + [% END %] - [% IF ( claimissues ) %] - + [% IF ( module == "claimissues" ) %] + [% ELSE %] - + [% END %] - [% IF ( reserves ) %] - + [% IF ( module == "reserves" ) %] + [% ELSE %] - + [% END %] - [% IF ( members ) %] - + [% IF ( module == "members" ) %] + [% ELSE %] - + [% END %] - [% IF ( serial ) %] - + [% IF ( module == "serial" ) %] + [% ELSE %] - + [% END %] - [% IF ( suggestions ) %] - + [% IF ( module == "suggestions" ) %] + [% ELSE %] - + [% END %] @@ -297,33 +286,49 @@ $(document).ready(function() {
  • -
  • - - [% IF is_html %] - - [% ELSE %] - - [% END %] -
  • -
  • - -
  • -
  • - -
  • -
  • - -
    -
  • - - [% IF code.search('DGST') %] Warning, this is a template for a Digest, as such, any references to branch data ( e.g. branches.branchname ) will refer to the borrower's home branch. [% END %] + [% FOREACH letter IN letters %] +
  • +
    + [% letter.message_transport_type %] +
      +
    1. + + + [% IF letter.is_html %] + + [% ELSE %] + + [% END %] +
    2. +
    3. + +
    4. +
    5. + + + + + + + +
      + +
      +
    6. +
    +
    +
  • + [% END %] + + + [% IF code.search('DGST') %] Warning, this is a template for a Digest, as such, any references to branch data ( e.g. branches.branchname ) will refer to the borrower's home branch. [% END %] -
    Cancel
    +
    Cancel
    [% END %] @@ -358,6 +363,7 @@ $(document).ready(function() { + diff --git a/t/db_dependent/Letters.t b/t/db_dependent/Letters.t index 77383594b0..9f5c9ace19 100644 --- a/t/db_dependent/Letters.t +++ b/t/db_dependent/Letters.t @@ -19,7 +19,7 @@ use Modern::Perl; -use Test::More tests => 4; +use Test::More tests => 5; use C4::Context; use C4::Letters; @@ -31,7 +31,9 @@ my $dbh = C4::Context->dbh; $dbh->{AutoCommit} = 0; $dbh->{RaiseError} = 1; -$dbh->do('DELETE FROM message_queue'); +$dbh->do(q|DELETE FROM letter|); +$dbh->do(q|DELETE FROM message_queue|); +$dbh->do(q|DELETE FROM message_transport_types|); my $borrowernumber = AddMember( firstname => 'Jane', @@ -40,6 +42,13 @@ my $borrowernumber = AddMember( branchcode => 'CPL', ); +$dbh->do(q| + INSERT INTO message_transport_types( message_transport_type ) VALUES ('email'), ('phone'), ('print'), ('sms') +|); + +my $mtts = C4::Letters::GetMessageTransportTypes(); +is_deeply( $mtts, ['email', 'phone', 'print', 'sms'], 'GetMessageTransportTypes returns all values' ); + my $message_id = C4::Letters::EnqueueLetter({ borrowernumber => $borrowernumber, message_transport_type => 'sms', diff --git a/tools/letter.pl b/tools/letter.pl index 7582e6616e..0f242f3b6a 100755 --- a/tools/letter.pl +++ b/tools/letter.pl @@ -47,14 +47,16 @@ use C4::Auth; use C4::Context; use C4::Output; use C4::Branch; # GetBranches +use C4::Letters; use C4::Members::Attributes; -# _letter_from_where($branchcode,$module, $code) +# _letter_from_where($branchcode,$module, $code, $mtt) # - return FROM WHERE clause and bind args for a letter sub _letter_from_where { - my ($branchcode, $module, $code) = @_; + my ($branchcode, $module, $code, $mtt) = @_; my $sql = q{FROM letter WHERE branchcode = ? AND module = ? AND code = ?}; - my @args = ($branchcode || '', $module, $code); + $sql .= q{ AND message_transport_type = ?} if $mtt ne '*'; + my @args = ( $branchcode || '', $module, $code, ($mtt ne '*' ? $mtt : ()) ); # Mysql is retarded. cause branchcode is part of the primary key it cannot be null. How does that # work with foreign key constraint I wonder... @@ -68,12 +70,12 @@ sub _letter_from_where { return ($sql, \@args); } -# letter_exists($branchcode,$module, $code) -# - return true if a letter with the given $branchcode, $module and $code exists -sub letter_exists { +# get_letters($branchcode,$module, $code, $mtt) +# - return letters with the given $branchcode, $module, $code and $mtt exists +sub get_letters { my ($sql, $args) = _letter_from_where(@_); my $dbh = C4::Context->dbh; - my $letter = $dbh->selectrow_hashref("SELECT * $sql", undef, @$args); + my $letter = $dbh->selectall_hashref("SELECT * $sql", 'message_transport_type', undef, @$args); return $letter; } @@ -90,7 +92,7 @@ my $searchfield = $input->param('searchfield'); my $script_name = '/cgi-bin/koha/tools/letter.pl'; our $branchcode = $input->param('branchcode'); my $code = $input->param('code'); -my $module = $input->param('module'); +my $module = $input->param('module') || ''; my $content = $input->param('content'); my $op = $input->param('op') || ''; my $dbh = C4::Context->dbh; @@ -135,7 +137,8 @@ elsif ( $op eq 'delete_confirm' ) { delete_confirm($branchcode, $module, $code); } elsif ( $op eq 'delete_confirmed' ) { - delete_confirmed($branchcode, $module, $code); + my $mtt = $input->param('message_transport_type'); + delete_confirmed($branchcode, $module, $code, $mtt); $op = q{}; # next operation is to return to default screen } else { @@ -152,25 +155,55 @@ if ($op) { output_html_with_http_headers $input, $cookie, $template->output; sub add_form { - my ($branchcode,$module, $code ) = @_; + my ( $branchcode,$module, $code ) = @_; - my $letter; + my $letters; # if code has been passed we can identify letter and its an update action if ($code) { - $letter = letter_exists($branchcode,$module, $code); + $letters = get_letters($branchcode,$module, $code, '*'); } - if ($letter) { - $template->param( modify => 1 ); - $template->param( code => $letter->{code} ); + + my $message_transport_types = GetMessageTransportTypes(); + my @letter_loop; + if ($letters) { + my $first_flag = 1; + for my $mtt ( @$message_transport_types ) { + if ( $first_flag ) { + $template->param( + modify => 1, + code => $code, + branchcode => $branchcode, + name => $letters->{$mtt}{name}, + ); + $first_flag = 0; + } + + push @letter_loop, { + message_transport_type => $mtt, + is_html => $letters->{$mtt}{is_html}, + title => $letters->{$mtt}{title}, + content => $letters->{$mtt}{content}, + }; + } } else { # initialize the new fields - $letter = { + for my $mtt ( @$message_transport_types ) { + $mtt = $mtt->{message_transport_type}; + push @letter_loop, { + message_transport_type => $mtt, + } + } + $template->param( branchcode => $branchcode, module => $module, - }; + ); $template->param( adding => 1 ); } + $template->param( + letters => \@letter_loop, + ); + my $field_selection; push @{$field_selection}, add_fields('branches'); if ($module eq 'reserves') { @@ -212,13 +245,7 @@ sub add_form { } $template->param( - branchcode => $letter->{branchcode}, - name => $letter->{name}, - is_html => $letter->{is_html}, - title => $letter->{title}, - content => $letter->{content}, module => $module, - $module => 1, branchloop => _branchloop($branchcode), SQLfieldname => $field_selection, ); @@ -233,22 +260,36 @@ sub add_validate { my $oldmodule = $input->param('oldmodule'); my $code = $input->param('code'); my $name = $input->param('name'); - my $is_html = $input->param('is_html'); - my $title = $input->param('title'); - my $content = $input->param('content'); - if (letter_exists($oldbranchcode,$oldmodule, $code)) { - $dbh->do( - q{UPDATE letter SET branchcode = ?, module = ?, name = ?, is_html = ?, title = ?, content = ? WHERE branchcode = ? AND module = ? AND code = ?}, - undef, - $branchcode, $module, $name, $is_html || 0, $title, $content, - $oldbranchcode, $oldmodule, $code - ); - } else { - $dbh->do( - q{INSERT INTO letter (branchcode,module,code,name,is_html,title,content) VALUES (?,?,?,?,?,?,?)}, - undef, - $branchcode, $module, $code, $name, $is_html || 0, $title, $content - ); + my @mtt = $input->param('message_transport_type'); + my @title = $input->param('title'); + my @content = $input->param('content'); + for my $mtt ( @mtt ) { + my $is_html = $input->param("is_html_$mtt"); + my $title = shift @title; + my $content = shift @content; + my $letter = get_letters($oldbranchcode,$oldmodule, $code, $mtt); + unless ( $title and $content ) { + delete_confirmed( $oldbranchcode, $oldmodule, $code, $mtt ); + next; + } + if ( exists $letter->{$mtt} ) { + $dbh->do( + q{ + UPDATE letter + SET branchcode = ?, module = ?, name = ?, is_html = ?, title = ?, content = ? + WHERE branchcode = ? AND module = ? AND code = ? AND message_transport_type = ? + }, + undef, + $branchcode, $module, $name, $is_html || 0, $title, $content, + $oldbranchcode, $oldmodule, $code, $mtt + ); + } else { + $dbh->do( + q{INSERT INTO letter (branchcode,module,code,name,is_html,title,content,message_transport_type) VALUES (?,?,?,?,?,?,?,?)}, + undef, + $branchcode, $module, $code, $name, $is_html || 0, $title, $content, $mtt + ); + } } # set up default display default_display($branchcode); @@ -261,31 +302,41 @@ sub add_copy { my $module = $input->param('module'); my $code = $input->param('code'); - return if letter_exists($branchcode,$module, $code); + return if keys %{ get_letters($branchcode,$module, $code, '*') }; - my $old_letter = letter_exists($oldbranchcode,$module, $code); + my $old_letters = get_letters($oldbranchcode,$module, $code, '*'); - $dbh->do( - q{INSERT INTO letter (branchcode,module,code,name,is_html,title,content) VALUES (?,?,?,?,?,?,?)}, - undef, - $branchcode, $module, $code, $old_letter->{name}, $old_letter->{is_html}, $old_letter->{title}, $old_letter->{content} - ); + my $message_transport_types = GetMessageTransportTypes(); + for my $mtt ( @$message_transport_types ) { + next unless exists $old_letters->{$mtt}; + my $old_letter = $old_letters->{$mtt}; + + $dbh->do( + q{INSERT INTO letter (branchcode,module,code,name,is_html,title,content,message_transport_type) VALUES (?,?,?,?,?,?,?,?)}, + undef, + $branchcode, $module, $code, $old_letter->{name}, $old_letter->{is_html}, $old_letter->{title}, $old_letter->{content}, $mtt + ); + } } sub delete_confirm { my ($branchcode, $module, $code) = @_; my $dbh = C4::Context->dbh; - my $letter = letter_exists($branchcode, $module, $code); - $template->param( branchcode => $branchcode, branchname => GetBranchName($branchcode) ); - $template->param( code => $code ); - $template->param( module => $module); - $template->param( name => $letter->{name}); + my $letter = get_letters($branchcode, $module, $code, '*'); + my @values = values %$letter; + $template->param( + branchcode => $branchcode, + branchname => GetBranchName($branchcode), + code => $code, + module => $module, + name => $values[0]->{name}, + ); return; } sub delete_confirmed { - my ($branchcode, $module, $code) = @_; - my ($sql, $args) = _letter_from_where($branchcode, $module, $code); + my ($branchcode, $module, $code, $mtt) = @_; + my ($sql, $args) = _letter_from_where($branchcode, $module, $code, $mtt); my $dbh = C4::Context->dbh; $dbh->do("DELETE $sql", undef, @$args); # setup default display for screen @@ -302,7 +353,8 @@ sub retrieve_letters { my ($sql, @where, @args); $sql = "SELECT branchcode, module, code, name, branchname FROM letter - LEFT OUTER JOIN branches USING (branchcode)"; + LEFT OUTER JOIN branches USING (branchcode) + "; if ($searchstring && $searchstring=~m/(\S+)/) { $searchstring = $1 . q{%}; push @where, 'code LIKE ?'; @@ -318,8 +370,9 @@ sub retrieve_letters { } $sql .= " WHERE ".join(" AND ", @where) if @where; + $sql .= " GROUP BY branchcode,module,code"; $sql .= " ORDER BY module, code, branchcode"; -# use Data::Dumper; die Dumper($sql, \@args); + return $dbh->selectall_arrayref($sql, { Slice => {} }, @args); } -- 2.39.5