View | Details | Raw Unified | Return to bug 11431
Collapse All | Expand All

(-)a/Koha/AudioAlert.pm (+79 lines)
Line 0 Link Here
1
package Koha::AudioAlert;
2
3
# Copyright ByWater Solutions 2014
4
#
5
# This file is part of Koha.
6
#
7
# Koha is free software; you can redistribute it and/or modify it under the
8
# terms of the GNU General Public License as published by the Free Software
9
# Foundation; either version 3 of the License, or (at your option) any later
10
# version.
11
#
12
# Koha is distributed in the hope that it will be useful, but WITHOUT ANY
13
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
14
# A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
15
#
16
# You should have received a copy of the GNU General Public License along
17
# with Koha; if not, write to the Free Software Foundation, Inc.,
18
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19
20
use Modern::Perl;
21
22
use Carp;
23
24
use Koha::Database;
25
26
use base qw(Koha::Object);
27
28
=head1 NAME
29
30
Koha::AudioAlert - Koha Borrower Object class
31
32
=head1 API
33
34
=head2 Class Methods
35
36
=head3 store
37
38
Override base store to set default precedence
39
if there is not one set already.
40
41
=cut
42
43
sub store {
44
    my ($self) = @_;
45
46
    $self->precedence( Koha::AudioAlerts->get_next_precedence() ) unless defined $self->precedence();
47
48
    return $self->SUPER::store();
49
}
50
51
=head3 move
52
53
$alert->move('up');
54
55
Changes the alert's precedence up, down, top, or bottom
56
57
=cut
58
59
sub move {
60
    my ( $self, $where ) = @_;
61
62
    return Koha::AudioAlerts->move( { audio_alert => $self, where => $where } );
63
}
64
65
=head3 type
66
67
=cut
68
69
sub type {
70
    return 'AudioAlert';
71
}
72
73
=head1 AUTHOR
74
75
Kyle M Hall <kyle@bywatersolutions.com>
76
77
=cut
78
79
1;
(-)a/Koha/AudioAlerts.pm (+157 lines)
Line 0 Link Here
1
package Koha::AudioAlerts;
2
3
# Copyright ByWater Solutions 2014
4
#
5
# This file is part of Koha.
6
#
7
# Koha is free software; you can redistribute it and/or modify it under the
8
# terms of the GNU General Public License as published by the Free Software
9
# Foundation; either version 3 of the License, or (at your option) any later
10
# version.
11
#
12
# Koha is distributed in the hope that it will be useful, but WITHOUT ANY
13
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
14
# A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
15
#
16
# You should have received a copy of the GNU General Public License along
17
# with Koha; if not, write to the Free Software Foundation, Inc.,
18
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19
20
use Modern::Perl;
21
22
use Carp;
23
24
use Koha::Database;
25
26
use Koha::AudioAlert;
27
28
use base qw(Koha::Objects);
29
30
=head1 NAME
31
32
Koha::AudioAlert - Koha Borrower Object class
33
34
=head1 API
35
36
=head2 Class Methods
37
38
=head3 search
39
40
Overrides default search such that
41
the default ordering is by precedence
42
43
=cut
44
45
sub search {
46
    my ( $self, $params, $attributes ) = @_;
47
48
    $attributes->{order_by} ||= 'precedence';
49
50
    return $self->SUPER::search( $params, $attributes );
51
}
52
53
=head3 get_next_precedence
54
55
Gets the next precedence value for audio alerts
56
57
=cut
58
59
sub get_next_precedence {
60
    my ($self) = @_;
61
62
    return $self->get_last_precedence() + 1;
63
}
64
65
=head3 get_last_precedence
66
67
Gets the last precedence value for audio alerts
68
69
=cut
70
71
sub get_last_precedence {
72
    my ($self) = @_;
73
74
    return $self->_resultset()->get_column('precedence')->max();
75
}
76
77
=head3 move
78
79
Koha::AudioAlerts->move( { audio_alert => $audio_alert, where => $where } );
80
81
Moves the given alert precedence 'up', 'down', 'top' or 'bottom'
82
83
=cut
84
85
sub move {
86
    my ( $self, $params ) = @_;
87
88
    my $alert = $params->{audio_alert};
89
    my $where = $params->{where};
90
91
    return unless ( $alert && $where );
92
93
    if ( $where eq 'up' ) {
94
        unless ( $alert->precedence() == 1 ) {
95
            my ($other) = $self->search( { precedence => $alert->precedence() - 1 } );
96
            $other->precedence( $alert->precedence() )->store();
97
            $alert->precedence( $alert->precedence() - 1 )->store();
98
        }
99
    }
100
    elsif ( $where eq 'down' ) {
101
        unless ( $alert->precedence() == $self->get_last_precedence() ) {
102
            my ($other) = $self->search( { precedence => $alert->precedence() + 1 } );
103
            $other->precedence( $alert->precedence() )->store();
104
            $alert->precedence( $alert->precedence() + 1 )->store();
105
        }
106
    }
107
    elsif ( $where eq 'top' ) {
108
        $alert->precedence(0)->store();
109
        $self->fix_precedences();
110
    }
111
    elsif ( $where eq 'bottom' ) {
112
        $alert->precedence( $self->get_next_precedence() )->store();
113
        $self->fix_precedences();
114
    }
115
}
116
117
=head3 fix_precedences
118
119
Koha::AudioAlerts->fix_precedences();
120
121
Updates precedence numbers to start with 1
122
and to have no gaps
123
124
=cut
125
126
sub fix_precedences {
127
    my ($self) = @_;
128
129
    my @alerts = $self->search();
130
131
    my $i = 1;
132
    map { $_->precedence( $i++ )->store() } @alerts;
133
}
134
135
=head3 type
136
137
=cut
138
139
sub type {
140
    return 'AudioAlert';
141
}
142
143
=head3 object_class
144
145
=cut
146
147
sub object_class {
148
    return 'Koha::AudioAlert';
149
}
150
151
=head1 AUTHOR
152
153
Kyle M Hall <kyle@bywatersolutions.com>
154
155
=cut
156
157
1;
(-)a/Koha/Object.pm (-1 / +5 lines)
Lines 255-261 sub AUTOLOAD { Link Here
255
    # Using direct setter/getter like $item->barcode() or $item->barcode($barcode);
255
    # Using direct setter/getter like $item->barcode() or $item->barcode($barcode);
256
    if ( grep {/^$method$/} @columns ) {
256
    if ( grep {/^$method$/} @columns ) {
257
        if ( @_ ) {
257
        if ( @_ ) {
258
            return $self->_result()->set_column( $method, @_ );
258
            warn "METHOD: $method";
259
            warn "VAL: " . $_[0];
260
            carp "TEST";
261
            $self->_result()->set_column( $method, @_ );
262
            return $self;
259
        } else {
263
        } else {
260
            my $value = $self->_result()->get_column( $method );
264
            my $value = $self->_result()->get_column( $method );
261
            return $value;
265
            return $value;
(-)a/Koha/Objects.pm (-3 / +3 lines)
Lines 94-110 my @objects = Koha::Objects->search($params); Link Here
94
=cut
94
=cut
95
95
96
sub search {
96
sub search {
97
    my ( $self, $params ) = @_;
97
    my ( $self, $params, $attributes ) = @_;
98
98
99
    if (wantarray) {
99
    if (wantarray) {
100
        my @dbic_rows = $self->_resultset()->search($params);
100
        my @dbic_rows = $self->_resultset()->search($params, $attributes);
101
101
102
        return $self->_wrap(@dbic_rows);
102
        return $self->_wrap(@dbic_rows);
103
103
104
    }
104
    }
105
    else {
105
    else {
106
        my $class = ref($self) ? ref($self) : $self;
106
        my $class = ref($self) ? ref($self) : $self;
107
        my $rs = $self->_resultset()->search($params);
107
        my $rs = $self->_resultset()->search($params, $attributes);
108
108
109
        return $class->_new_from_dbic($rs);
109
        return $class->_new_from_dbic($rs);
110
    }
110
    }
(-)a/Koha/Template/Plugin/Koha.pm (+7 lines)
Lines 19-24 package Koha::Template::Plugin::Koha; Link Here
19
19
20
use Modern::Perl;
20
use Modern::Perl;
21
use Encode qw( encode );
21
use Encode qw( encode );
22
use JSON;
22
23
23
use base qw( Template::Plugin );
24
use base qw( Template::Plugin );
24
25
Lines 45-48 sub Preference { Link Here
45
    return encode('UTF-8', C4::Context->preference( $pref ) );
46
    return encode('UTF-8', C4::Context->preference( $pref ) );
46
}
47
}
47
48
49
sub AudioAlerts {
50
    my $dbh = C4::Context->dbh;
51
    my $audio_alerts = $dbh->selectall_arrayref( 'SELECT * FROM audio_alerts ORDER BY precedence', { Slice => {} } );
52
    return encode_json($audio_alerts);
53
}
54
48
1;
55
1;
(-)a/admin/audio_alerts.pl (+60 lines)
Line 0 Link Here
1
#!/usr/bin/perl
2
3
# Copyright 2014 ByWater Solutions
4
#
5
# This file is part of Koha.
6
#
7
# Koha is free software; you can redistribute it and/or modify it under the
8
# terms of the GNU General Public License as published by the Free Software
9
# Foundation; either version 3 of the License, or (at your option) any later
10
# version.
11
#
12
# Koha is distributed in the hope that it will be useful, but WITHOUT ANY
13
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
14
# A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
15
#
16
# You should have received a copy of the GNU General Public License along
17
# with Koha; if not, write to the Free Software Foundation, Inc.,
18
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19
20
use Modern::Perl;
21
22
use CGI;
23
use C4::Auth;
24
use C4::Output;
25
use Koha::AudioAlert;
26
use Koha::AudioAlerts;
27
28
my $cgi = new CGI;
29
30
my $selector = $cgi->param('selector');
31
my $sound    = $cgi->param('sound');
32
my $id       = $cgi->param('id');
33
my $action     = $cgi->param('action');
34
my $where    = $cgi->param('where');
35
my @delete   = $cgi->param('delete');
36
37
my ( $template, $loggedinuser, $cookie ) = get_template_and_user(
38
    {
39
        template_name   => "admin/audio_alerts.tt",
40
        query           => $cgi,
41
        type            => "intranet",
42
        authnotrequired => 0,
43
        flagsrequired   => { parameters => 'parameters_remaining_permissions' },
44
        debug           => 1,
45
    }
46
);
47
48
if ( $selector && $sound ) {
49
    Koha::AudioAlert->new( { selector => $selector, sound => $sound } )->store();
50
}
51
52
map { Koha::AudioAlerts->find($_)->delete() } @delete;
53
54
if ( $id && $action && $where && $action eq 'move' ) {
55
    Koha::AudioAlerts->find($id)->move($where);
56
}
57
58
$template->param( audio_alerts => scalar Koha::AudioAlerts->search() );
59
60
output_html_with_http_headers $cgi, $cookie, $template->output;
(-)a/koha-tmpl/intranet-tmpl/prog/en/includes/admin-menu.inc (+1 lines)
Lines 64-69 Link Here
64
    <li><a href="/cgi-bin/koha/admin/z3950servers.pl">Z39.50/SRU servers</a></li>
64
    <li><a href="/cgi-bin/koha/admin/z3950servers.pl">Z39.50/SRU servers</a></li>
65
    <li><a href="/cgi-bin/koha/admin/didyoumean.pl">Did you mean?</a></li>
65
    <li><a href="/cgi-bin/koha/admin/didyoumean.pl">Did you mean?</a></li>
66
    <li><a href="/cgi-bin/koha/admin/columns_settings.pl">Columns settings</a></li>
66
    <li><a href="/cgi-bin/koha/admin/columns_settings.pl">Columns settings</a></li>
67
    <li><a href="/cgi-bin/koha/admin/audio_alerts.pl">Audio alerts</a></li>
67
</ul>
68
</ul>
68
</div>
69
</div>
69
</div>
70
</div>
(-)a/koha-tmpl/intranet-tmpl/prog/en/includes/doc-head-close.inc (-26 / +7 lines)
Lines 64-105 Link Here
64
    </script>
64
    </script>
65
[% END %]
65
[% END %]
66
66
67
[% IF AudioAlerts %]
67
[% IF Koha.Preference('AudioAlerts') %]
68
    <script type="text/javascript">
68
    <script type="text/javascript">
69
        //<![CDATA[
69
        //<![CDATA[
70
            var AUDIO_ALERT_PATH = '[% interface %]/[% theme %]/sound/';
70
            var AUDIO_ALERT_PATH = '[% interface %]/[% theme %]/sound/';
71
            var AUDIO_ALERT_ACTION  = '[% Koha.Preference("OverrideAudioAlertAction")  || "opening.ogg"  %]';
71
            var AUDIO_ALERTS = JSON.parse( '[% Koha.AudioAlerts | replace( "'", "\\'" ) %]' );
72
            var AUDIO_ALERT_WARNING = '[% Koha.Preference("OverrideAudioAlertWarning") || "critical.ogg" %]';
73
            var AUDIO_ALERT_SUCCESS = '[% Koha.Preference("OverrideAudioAlertSuccess") || "beep.ogg"     %]';
74
            var AUDIO_ALERT_SELECTOR_ACTION  = '[% Koha.Preference("AudioAlertSelectorAction")  | replace( "'", "\\'" ) %]';
75
            var AUDIO_ALERT_SELECTOR_WARNING = '[% Koha.Preference("AudioAlertSelectorWarning") | replace( "'", "\\'" ) %]';
76
            var AUDIO_ALERT_SELECTOR_SUCCESS = '[% Koha.Preference("AudioAlertSelectorSuccess") | replace( "'", "\\'" ) %]';
77
            var AUDIO_ALERT_SELECTOR_CUSTOM = JSON.parse( '{ [% String.new( Koha.Preference("AudioAlertsCustom") ).collapse | replace( "'", "\\'" ) %] }' );
78
        //]]>
72
        //]]>
79
73
80
        $( document ).ready(function() {
74
        $( document ).ready(function() {
81
            var no_sound_played = true;
75
            if ( AUDIO_ALERTS ) {
82
            if ( Object.keys(AUDIO_ALERT_SELECTOR_CUSTOM) ) {
76
                for ( var k in AUDIO_ALERTS ) {
83
                for ( var k in AUDIO_ALERT_SELECTOR_CUSTOM ) {
77
                    var alert = AUDIO_ALERTS[k];
84
                    if ( $(k).length ) {
78
                    if ( $( alert.selector ).length ) {
85
                        playSound( AUDIO_ALERT_SELECTOR_CUSTOM[k] );
79
                        playSound( alert.sound );
86
                        no_sound_played = false;
87
                        break;
80
                        break;
88
                    }
81
                    }
89
                }
82
                }
90
            }
83
            }
91
92
            if ( no_sound_played ) {
93
                if ( $( AUDIO_ALERT_SELECTOR_ACTION ).length ) {
94
                    playSoundAction();
95
                }
96
                else if ( $( AUDIO_ALERT_SELECTOR_WARNING ).length ) {
97
                    playSoundWarning();
98
                }
99
                else if ( $( AUDIO_ALERT_SELECTOR_SUCCESS ).length ) {
100
                    playSoundSuccess();
101
                }
102
            }
103
        });
84
        });
104
    </script>
85
    </script>
105
[% END %]
86
[% END %]
(-)a/koha-tmpl/intranet-tmpl/prog/en/js/staff-global.js (-12 lines)
Lines 128-142 function playSound( sound ) { Link Here
128
    }
128
    }
129
    document.getElementById("audio-alert").innerHTML = '<audio src="' + sound + '" autoplay="autoplay" autobuffer="autobuffer"></audio>';
129
    document.getElementById("audio-alert").innerHTML = '<audio src="' + sound + '" autoplay="autoplay" autobuffer="autobuffer"></audio>';
130
}
130
}
131
132
function playSoundWarning() {
133
    playSound( AUDIO_ALERT_WARNING );
134
}
135
136
function playSoundAction() {
137
    playSound( AUDIO_ALERT_ACTION );
138
}
139
140
function playSoundSuccess() {
141
    playSound( AUDIO_ALERT_SUCCESS );
142
}
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/admin-home.tt (+2 lines)
Lines 104-109 Link Here
104
    <dd>Choose which plugins to use to suggest searches to patrons and staff.</dd>
104
    <dd>Choose which plugins to use to suggest searches to patrons and staff.</dd>
105
    <dt><a href="/cgi-bin/koha/admin/columns_settings.pl">Configure columns</a></dt>
105
    <dt><a href="/cgi-bin/koha/admin/columns_settings.pl">Configure columns</a></dt>
106
    <dd>Hide or show columns for tables.</dd>
106
    <dd>Hide or show columns for tables.</dd>
107
    <dt><a href="/cgi-bin/koha/admin/audio_alerts.pl">Audio alerts</a></dt>
108
    <dd>Define which events trigger which sounds</dd>
107
</dl>
109
</dl>
108
</div>
110
</div>
109
111
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/audio_alerts.tt (-1 / +131 lines)
Line 0 Link Here
0
- 
1
[% INCLUDE 'doc-head-open.inc' %]
2
<title>Koha &rsaquo; Administration &rsaquo; Audio alerts</title>
3
[% INCLUDE 'doc-head-close.inc' %]
4
5
<script type="text/javascript">
6
$( document ).ready(function() {
7
    $.ajax({
8
        //This will retrieve the contents of the folder if the folder is configured as 'browsable'
9
        url: AUDIO_ALERT_PATH,
10
        success: function (data) {
11
            $("#fileNames").html('<ul>');
12
            //List all png or jpg or gif file names in the page
13
            $(data).find('a:contains("ogg")').each(function () {
14
                var filename = this.href.split('/').pop();
15
                $('#koha-sounds').append($('<option>', { value : filename }).text(filename));
16
            });
17
        }
18
    });
19
20
    $('#koha-sounds').on('change', function() {
21
        $('#sound').val( this.value );
22
    });
23
24
    $('#koha-sounds').on('change', function() {
25
        $('#sound').val( this.value );
26
    });
27
28
    $('#play-sound').on('click', function() {
29
        playSound( $('#sound').val() );
30
        return false;
31
    });
32
33
    $('#new-alert-form').on('submit', function() {
34
        if ( ! $('#selector').val() ) {
35
            alert(_("You must enter a selector!"));
36
            return false;
37
        } else if ( ! $('#sound').val() ) {
38
            alert(_("You must choose a sound!"));
39
            return false;
40
        } else {
41
            return true;
42
        }
43
    });
44
45
    $('#delete-alert-form').on('submit', function() {
46
        return confirm(_("Are you sure you want to delete the selected audio alerts?"));
47
    });
48
});
49
</script>
50
51
</head>
52
<body>
53
[% INCLUDE 'header.inc' %]
54
[% INCLUDE 'patrons-admin-search.inc' %]
55
56
<div id="breadcrumbs"><a href="/cgi-bin/koha/mainpage.pl">Home</a> &rsaquo; <a href="/cgi-bin/koha/admin/admin-home.pl">Administration</a> &rsaquo; Audio alerts</div>
57
58
<div id="doc3" class="yui-t2">
59
    <div id="bd">
60
        <div id="yui-main">
61
            <div class="yui-b">
62
                <form id="new-alert-form" action="audio_alerts.pl" method="post">
63
                    <fieldset class="form-inline">
64
                        <legend>Add new alert</legend>
65
66
                        <input id="selector" name="selector" type="text" class="input-large" placeholder="selector" />
67
                        <input id="sound" name="sound" type="text" class="input-large" placeholder="sound" />
68
69
                        <button id="play-sound" class="btn"><i class="icon-play"></i> Play sound</button>
70
71
                        <br/>
72
73
                        <select id="koha-sounds">
74
                            <option value="">Select built-in sound</option>
75
                        </select>
76
77
                        <button id="save-alert" type="submit" class="btn"><i class="icon-hdd"></i> Save alert</button>
78
                    </fieldset>
79
                </form>
80
81
                <form id="delete-alert-form" action="audio_alerts.pl" method="post">
82
                    <table>
83
                        <thead>
84
                            <tr>
85
                                <th>&nbsp;</th>
86
                                <th>Precedence</th>
87
                                <th>&nbsp;</th>
88
                                <th>Selector</th>
89
                                <th>Sound</th>
90
                            </tr>
91
                        </thead>
92
93
                        <tbody>
94
                            [% FOREACH a IN audio_alerts %]
95
                                <tr>
96
                                    <td><input type="checkbox" name="delete" value="[% a.id %]" /></td>
97
                                    <td>[% a.precedence %]</td>
98
                                    <td style="white-space:nowrap;">
99
                                        <a title="Move alert up" href="audio_alerts.pl?action=move&amp;where=up&amp;id=[% a.id %]">
100
                                            <img src="[% interface %]/[% theme %]/img/go-up.png" border="0" alt="Go up" />
101
                                        </a>
102
103
                                        <a title="Move alert to top" href="audio_alerts.pl?action=move&amp;where=top&amp;id=[% a.id %]">
104
                                            <img src="[% interface %]/[% theme %]/img/go-top.png" border="0" alt="Go top" />
105
                                        </a>
106
107
                                        <a title="Move alert to bottom" href="audio_alerts.pl?action=move&amp;where=bottom&amp;id=[% a.id %]">
108
                                            <img src="[% interface %]/[% theme %]/img/go-bottom.png" border="0" alt="Go bottom" />
109
                                        </a>
110
111
                                        <a title="Move alert down" href="audio_alerts.pl?action=move&amp;where=down&amp;id=[% a.id %]">
112
                                            <img src="[% interface %]/[% theme %]/img/go-down.png" border="0" alt="Go down" />
113
                                        </a>
114
                                    </td>
115
                                    <td>[% a.selector %]</td>
116
                                    <td>[% a.sound %]</td>
117
                                </tr>
118
                            [% END %]
119
                        </tbody>
120
                    </table>
121
122
                    <p/>
123
                    <button id="delete-alerts" type="submit" class="btn"><i class="icon-trash"></i> Delete selected alerts</button>
124
                </form>
125
            </div>
126
        </div>
127
    <div class="yui-b">
128
[% INCLUDE 'admin-menu.inc' %]
129
</div>
130
</div>
131
[% INCLUDE 'intranet-bottom.inc' %]

Return to bug 11431