Bugzilla – Attachment 34644 Details for
Bug 11431
Custom notification sounds
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
Bug 11431 [8] - Add audio alerts editor
Bug-11431-8---Add-audio-alerts-editor.patch (text/plain), 20.98 KB, created by
Kyle M Hall (khall)
on 2014-12-22 18:51:06 UTC
(
hide
)
Description:
Bug 11431 [8] - Add audio alerts editor
Filename:
MIME Type:
Creator:
Kyle M Hall (khall)
Created:
2014-12-22 18:51:06 UTC
Size:
20.98 KB
patch
obsolete
>From 62865dece92efd6222604f67b4d1ff4745faece5 Mon Sep 17 00:00:00 2001 >From: Kyle M Hall <kyle@bywatersolutions.com> >Date: Mon, 22 Dec 2014 05:32:05 -0500 >Subject: [PATCH] Bug 11431 [8] - Add audio alerts editor > >--- > Koha/AudioAlert.pm | 79 ++++++++++ > Koha/AudioAlerts.pm | 157 ++++++++++++++++++++ > Koha/Object.pm | 6 +- > Koha/Objects.pm | 6 +- > Koha/Template/Plugin/Koha.pm | 7 + > admin/audio_alerts.pl | 60 ++++++++ > .../intranet-tmpl/prog/en/includes/admin-menu.inc | 1 + > .../prog/en/includes/doc-head-close.inc | 33 +---- > koha-tmpl/intranet-tmpl/prog/en/js/staff-global.js | 12 -- > .../prog/en/modules/admin/admin-home.tt | 2 + > .../prog/en/modules/admin/audio_alerts.tt | 131 ++++++++++++++++ > 11 files changed, 452 insertions(+), 42 deletions(-) > create mode 100644 Koha/AudioAlert.pm > create mode 100644 Koha/AudioAlerts.pm > create mode 100755 admin/audio_alerts.pl > create mode 100644 koha-tmpl/intranet-tmpl/prog/en/modules/admin/audio_alerts.tt > >diff --git a/Koha/AudioAlert.pm b/Koha/AudioAlert.pm >new file mode 100644 >index 0000000..4bedbb9 >--- /dev/null >+++ b/Koha/AudioAlert.pm >@@ -0,0 +1,79 @@ >+package Koha::AudioAlert; >+ >+# Copyright ByWater Solutions 2014 >+# >+# 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 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, write to the Free Software Foundation, Inc., >+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. >+ >+use Modern::Perl; >+ >+use Carp; >+ >+use Koha::Database; >+ >+use base qw(Koha::Object); >+ >+=head1 NAME >+ >+Koha::AudioAlert - Koha Borrower Object class >+ >+=head1 API >+ >+=head2 Class Methods >+ >+=head3 store >+ >+Override base store to set default precedence >+if there is not one set already. >+ >+=cut >+ >+sub store { >+ my ($self) = @_; >+ >+ $self->precedence( Koha::AudioAlerts->get_next_precedence() ) unless defined $self->precedence(); >+ >+ return $self->SUPER::store(); >+} >+ >+=head3 move >+ >+$alert->move('up'); >+ >+Changes the alert's precedence up, down, top, or bottom >+ >+=cut >+ >+sub move { >+ my ( $self, $where ) = @_; >+ >+ return Koha::AudioAlerts->move( { audio_alert => $self, where => $where } ); >+} >+ >+=head3 type >+ >+=cut >+ >+sub type { >+ return 'AudioAlert'; >+} >+ >+=head1 AUTHOR >+ >+Kyle M Hall <kyle@bywatersolutions.com> >+ >+=cut >+ >+1; >diff --git a/Koha/AudioAlerts.pm b/Koha/AudioAlerts.pm >new file mode 100644 >index 0000000..1127297 >--- /dev/null >+++ b/Koha/AudioAlerts.pm >@@ -0,0 +1,157 @@ >+package Koha::AudioAlerts; >+ >+# Copyright ByWater Solutions 2014 >+# >+# 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 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, write to the Free Software Foundation, Inc., >+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. >+ >+use Modern::Perl; >+ >+use Carp; >+ >+use Koha::Database; >+ >+use Koha::AudioAlert; >+ >+use base qw(Koha::Objects); >+ >+=head1 NAME >+ >+Koha::AudioAlert - Koha Borrower Object class >+ >+=head1 API >+ >+=head2 Class Methods >+ >+=head3 search >+ >+Overrides default search such that >+the default ordering is by precedence >+ >+=cut >+ >+sub search { >+ my ( $self, $params, $attributes ) = @_; >+ >+ $attributes->{order_by} ||= 'precedence'; >+ >+ return $self->SUPER::search( $params, $attributes ); >+} >+ >+=head3 get_next_precedence >+ >+Gets the next precedence value for audio alerts >+ >+=cut >+ >+sub get_next_precedence { >+ my ($self) = @_; >+ >+ return $self->get_last_precedence() + 1; >+} >+ >+=head3 get_last_precedence >+ >+Gets the last precedence value for audio alerts >+ >+=cut >+ >+sub get_last_precedence { >+ my ($self) = @_; >+ >+ return $self->_resultset()->get_column('precedence')->max(); >+} >+ >+=head3 move >+ >+Koha::AudioAlerts->move( { audio_alert => $audio_alert, where => $where } ); >+ >+Moves the given alert precedence 'up', 'down', 'top' or 'bottom' >+ >+=cut >+ >+sub move { >+ my ( $self, $params ) = @_; >+ >+ my $alert = $params->{audio_alert}; >+ my $where = $params->{where}; >+ >+ return unless ( $alert && $where ); >+ >+ if ( $where eq 'up' ) { >+ unless ( $alert->precedence() == 1 ) { >+ my ($other) = $self->search( { precedence => $alert->precedence() - 1 } ); >+ $other->precedence( $alert->precedence() )->store(); >+ $alert->precedence( $alert->precedence() - 1 )->store(); >+ } >+ } >+ elsif ( $where eq 'down' ) { >+ unless ( $alert->precedence() == $self->get_last_precedence() ) { >+ my ($other) = $self->search( { precedence => $alert->precedence() + 1 } ); >+ $other->precedence( $alert->precedence() )->store(); >+ $alert->precedence( $alert->precedence() + 1 )->store(); >+ } >+ } >+ elsif ( $where eq 'top' ) { >+ $alert->precedence(0)->store(); >+ $self->fix_precedences(); >+ } >+ elsif ( $where eq 'bottom' ) { >+ $alert->precedence( $self->get_next_precedence() )->store(); >+ $self->fix_precedences(); >+ } >+} >+ >+=head3 fix_precedences >+ >+Koha::AudioAlerts->fix_precedences(); >+ >+Updates precedence numbers to start with 1 >+and to have no gaps >+ >+=cut >+ >+sub fix_precedences { >+ my ($self) = @_; >+ >+ my @alerts = $self->search(); >+ >+ my $i = 1; >+ map { $_->precedence( $i++ )->store() } @alerts; >+} >+ >+=head3 type >+ >+=cut >+ >+sub type { >+ return 'AudioAlert'; >+} >+ >+=head3 object_class >+ >+=cut >+ >+sub object_class { >+ return 'Koha::AudioAlert'; >+} >+ >+=head1 AUTHOR >+ >+Kyle M Hall <kyle@bywatersolutions.com> >+ >+=cut >+ >+1; >diff --git a/Koha/Object.pm b/Koha/Object.pm >index bc2746f..1be2cf5 100644 >--- a/Koha/Object.pm >+++ b/Koha/Object.pm >@@ -255,7 +255,11 @@ sub AUTOLOAD { > # Using direct setter/getter like $item->barcode() or $item->barcode($barcode); > if ( grep {/^$method$/} @columns ) { > if ( @_ ) { >- return $self->_result()->set_column( $method, @_ ); >+ warn "METHOD: $method"; >+ warn "VAL: " . $_[0]; >+ carp "TEST"; >+ $self->_result()->set_column( $method, @_ ); >+ return $self; > } else { > my $value = $self->_result()->get_column( $method ); > return $value; >diff --git a/Koha/Objects.pm b/Koha/Objects.pm >index 5413fb6..6223d89 100644 >--- a/Koha/Objects.pm >+++ b/Koha/Objects.pm >@@ -94,17 +94,17 @@ my @objects = Koha::Objects->search($params); > =cut > > sub search { >- my ( $self, $params ) = @_; >+ my ( $self, $params, $attributes ) = @_; > > if (wantarray) { >- my @dbic_rows = $self->_resultset()->search($params); >+ my @dbic_rows = $self->_resultset()->search($params, $attributes); > > return $self->_wrap(@dbic_rows); > > } > else { > my $class = ref($self) ? ref($self) : $self; >- my $rs = $self->_resultset()->search($params); >+ my $rs = $self->_resultset()->search($params, $attributes); > > return $class->_new_from_dbic($rs); > } >diff --git a/Koha/Template/Plugin/Koha.pm b/Koha/Template/Plugin/Koha.pm >index 6b95e3b..3aebee3 100644 >--- a/Koha/Template/Plugin/Koha.pm >+++ b/Koha/Template/Plugin/Koha.pm >@@ -19,6 +19,7 @@ package Koha::Template::Plugin::Koha; > > use Modern::Perl; > use Encode qw( encode ); >+use JSON; > > use base qw( Template::Plugin ); > >@@ -45,4 +46,10 @@ sub Preference { > return encode('UTF-8', C4::Context->preference( $pref ) ); > } > >+sub AudioAlerts { >+ my $dbh = C4::Context->dbh; >+ my $audio_alerts = $dbh->selectall_arrayref( 'SELECT * FROM audio_alerts ORDER BY precedence', { Slice => {} } ); >+ return encode_json($audio_alerts); >+} >+ > 1; >diff --git a/admin/audio_alerts.pl b/admin/audio_alerts.pl >new file mode 100755 >index 0000000..f62bacd >--- /dev/null >+++ b/admin/audio_alerts.pl >@@ -0,0 +1,60 @@ >+#!/usr/bin/perl >+ >+# Copyright 2014 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 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, write to the Free Software Foundation, Inc., >+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. >+ >+use Modern::Perl; >+ >+use CGI; >+use C4::Auth; >+use C4::Output; >+use Koha::AudioAlert; >+use Koha::AudioAlerts; >+ >+my $cgi = new CGI; >+ >+my $selector = $cgi->param('selector'); >+my $sound = $cgi->param('sound'); >+my $id = $cgi->param('id'); >+my $action = $cgi->param('action'); >+my $where = $cgi->param('where'); >+my @delete = $cgi->param('delete'); >+ >+my ( $template, $loggedinuser, $cookie ) = get_template_and_user( >+ { >+ template_name => "admin/audio_alerts.tt", >+ query => $cgi, >+ type => "intranet", >+ authnotrequired => 0, >+ flagsrequired => { parameters => 'parameters_remaining_permissions' }, >+ debug => 1, >+ } >+); >+ >+if ( $selector && $sound ) { >+ Koha::AudioAlert->new( { selector => $selector, sound => $sound } )->store(); >+} >+ >+map { Koha::AudioAlerts->find($_)->delete() } @delete; >+ >+if ( $id && $action && $where && $action eq 'move' ) { >+ Koha::AudioAlerts->find($id)->move($where); >+} >+ >+$template->param( audio_alerts => scalar Koha::AudioAlerts->search() ); >+ >+output_html_with_http_headers $cgi, $cookie, $template->output; >diff --git a/koha-tmpl/intranet-tmpl/prog/en/includes/admin-menu.inc b/koha-tmpl/intranet-tmpl/prog/en/includes/admin-menu.inc >index 281bb54..e38b0b4 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/includes/admin-menu.inc >+++ b/koha-tmpl/intranet-tmpl/prog/en/includes/admin-menu.inc >@@ -64,6 +64,7 @@ > <li><a href="/cgi-bin/koha/admin/z3950servers.pl">Z39.50/SRU servers</a></li> > <li><a href="/cgi-bin/koha/admin/didyoumean.pl">Did you mean?</a></li> > <li><a href="/cgi-bin/koha/admin/columns_settings.pl">Columns settings</a></li> >+ <li><a href="/cgi-bin/koha/admin/audio_alerts.pl">Audio alerts</a></li> > </ul> > </div> > </div> >diff --git a/koha-tmpl/intranet-tmpl/prog/en/includes/doc-head-close.inc b/koha-tmpl/intranet-tmpl/prog/en/includes/doc-head-close.inc >index 77b6381..cfa8254 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/includes/doc-head-close.inc >+++ b/koha-tmpl/intranet-tmpl/prog/en/includes/doc-head-close.inc >@@ -64,42 +64,23 @@ > </script> > [% END %] > >-[% IF AudioAlerts %] >+[% IF Koha.Preference('AudioAlerts') %] > <script type="text/javascript"> > //<![CDATA[ > var AUDIO_ALERT_PATH = '[% interface %]/[% theme %]/sound/'; >- var AUDIO_ALERT_ACTION = '[% Koha.Preference("OverrideAudioAlertAction") || "opening.ogg" %]'; >- var AUDIO_ALERT_WARNING = '[% Koha.Preference("OverrideAudioAlertWarning") || "critical.ogg" %]'; >- var AUDIO_ALERT_SUCCESS = '[% Koha.Preference("OverrideAudioAlertSuccess") || "beep.ogg" %]'; >- var AUDIO_ALERT_SELECTOR_ACTION = '[% Koha.Preference("AudioAlertSelectorAction") | replace( "'", "\\'" ) %]'; >- var AUDIO_ALERT_SELECTOR_WARNING = '[% Koha.Preference("AudioAlertSelectorWarning") | replace( "'", "\\'" ) %]'; >- var AUDIO_ALERT_SELECTOR_SUCCESS = '[% Koha.Preference("AudioAlertSelectorSuccess") | replace( "'", "\\'" ) %]'; >- var AUDIO_ALERT_SELECTOR_CUSTOM = JSON.parse( '{ [% String.new( Koha.Preference("AudioAlertsCustom") ).collapse | replace( "'", "\\'" ) %] }' ); >+ var AUDIO_ALERTS = JSON.parse( '[% Koha.AudioAlerts | replace( "'", "\\'" ) %]' ); > //]]> > > $( document ).ready(function() { >- var no_sound_played = true; >- if ( Object.keys(AUDIO_ALERT_SELECTOR_CUSTOM) ) { >- for ( var k in AUDIO_ALERT_SELECTOR_CUSTOM ) { >- if ( $(k).length ) { >- playSound( AUDIO_ALERT_SELECTOR_CUSTOM[k] ); >- no_sound_played = false; >+ if ( AUDIO_ALERTS ) { >+ for ( var k in AUDIO_ALERTS ) { >+ var alert = AUDIO_ALERTS[k]; >+ if ( $( alert.selector ).length ) { >+ playSound( alert.sound ); > break; > } > } > } >- >- if ( no_sound_played ) { >- if ( $( AUDIO_ALERT_SELECTOR_ACTION ).length ) { >- playSoundAction(); >- } >- else if ( $( AUDIO_ALERT_SELECTOR_WARNING ).length ) { >- playSoundWarning(); >- } >- else if ( $( AUDIO_ALERT_SELECTOR_SUCCESS ).length ) { >- playSoundSuccess(); >- } >- } > }); > </script> > [% END %] >diff --git a/koha-tmpl/intranet-tmpl/prog/en/js/staff-global.js b/koha-tmpl/intranet-tmpl/prog/en/js/staff-global.js >index e6f03a2..fd0f33e 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/js/staff-global.js >+++ b/koha-tmpl/intranet-tmpl/prog/en/js/staff-global.js >@@ -128,15 +128,3 @@ function playSound( sound ) { > } > document.getElementById("audio-alert").innerHTML = '<audio src="' + sound + '" autoplay="autoplay" autobuffer="autobuffer"></audio>'; > } >- >-function playSoundWarning() { >- playSound( AUDIO_ALERT_WARNING ); >-} >- >-function playSoundAction() { >- playSound( AUDIO_ALERT_ACTION ); >-} >- >-function playSoundSuccess() { >- playSound( AUDIO_ALERT_SUCCESS ); >-} >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/admin-home.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/admin-home.tt >index 02bc60a..27068ae 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/admin-home.tt >+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/admin-home.tt >@@ -104,6 +104,8 @@ > <dd>Choose which plugins to use to suggest searches to patrons and staff.</dd> > <dt><a href="/cgi-bin/koha/admin/columns_settings.pl">Configure columns</a></dt> > <dd>Hide or show columns for tables.</dd> >+ <dt><a href="/cgi-bin/koha/admin/audio_alerts.pl">Audio alerts</a></dt> >+ <dd>Define which events trigger which sounds</dd> > </dl> > </div> > >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/audio_alerts.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/audio_alerts.tt >new file mode 100644 >index 0000000..a64f9b6 >--- /dev/null >+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/audio_alerts.tt >@@ -0,0 +1,131 @@ >+[% INCLUDE 'doc-head-open.inc' %] >+<title>Koha › Administration › Audio alerts</title> >+[% INCLUDE 'doc-head-close.inc' %] >+ >+<script type="text/javascript"> >+$( document ).ready(function() { >+ $.ajax({ >+ //This will retrieve the contents of the folder if the folder is configured as 'browsable' >+ url: AUDIO_ALERT_PATH, >+ success: function (data) { >+ $("#fileNames").html('<ul>'); >+ //List all png or jpg or gif file names in the page >+ $(data).find('a:contains("ogg")').each(function () { >+ var filename = this.href.split('/').pop(); >+ $('#koha-sounds').append($('<option>', { value : filename }).text(filename)); >+ }); >+ } >+ }); >+ >+ $('#koha-sounds').on('change', function() { >+ $('#sound').val( this.value ); >+ }); >+ >+ $('#koha-sounds').on('change', function() { >+ $('#sound').val( this.value ); >+ }); >+ >+ $('#play-sound').on('click', function() { >+ playSound( $('#sound').val() ); >+ return false; >+ }); >+ >+ $('#new-alert-form').on('submit', function() { >+ if ( ! $('#selector').val() ) { >+ alert(_("You must enter a selector!")); >+ return false; >+ } else if ( ! $('#sound').val() ) { >+ alert(_("You must choose a sound!")); >+ return false; >+ } else { >+ return true; >+ } >+ }); >+ >+ $('#delete-alert-form').on('submit', function() { >+ return confirm(_("Are you sure you want to delete the selected audio alerts?")); >+ }); >+}); >+</script> >+ >+</head> >+<body> >+[% INCLUDE 'header.inc' %] >+[% INCLUDE 'patrons-admin-search.inc' %] >+ >+<div id="breadcrumbs"><a href="/cgi-bin/koha/mainpage.pl">Home</a> › <a href="/cgi-bin/koha/admin/admin-home.pl">Administration</a> › Audio alerts</div> >+ >+<div id="doc3" class="yui-t2"> >+ <div id="bd"> >+ <div id="yui-main"> >+ <div class="yui-b"> >+ <form id="new-alert-form" action="audio_alerts.pl" method="post"> >+ <fieldset class="form-inline"> >+ <legend>Add new alert</legend> >+ >+ <input id="selector" name="selector" type="text" class="input-large" placeholder="selector" /> >+ <input id="sound" name="sound" type="text" class="input-large" placeholder="sound" /> >+ >+ <button id="play-sound" class="btn"><i class="icon-play"></i> Play sound</button> >+ >+ <br/> >+ >+ <select id="koha-sounds"> >+ <option value="">Select built-in sound</option> >+ </select> >+ >+ <button id="save-alert" type="submit" class="btn"><i class="icon-hdd"></i> Save alert</button> >+ </fieldset> >+ </form> >+ >+ <form id="delete-alert-form" action="audio_alerts.pl" method="post"> >+ <table> >+ <thead> >+ <tr> >+ <th> </th> >+ <th>Precedence</th> >+ <th> </th> >+ <th>Selector</th> >+ <th>Sound</th> >+ </tr> >+ </thead> >+ >+ <tbody> >+ [% FOREACH a IN audio_alerts %] >+ <tr> >+ <td><input type="checkbox" name="delete" value="[% a.id %]" /></td> >+ <td>[% a.precedence %]</td> >+ <td style="white-space:nowrap;"> >+ <a title="Move alert up" href="audio_alerts.pl?action=move&where=up&id=[% a.id %]"> >+ <img src="[% interface %]/[% theme %]/img/go-up.png" border="0" alt="Go up" /> >+ </a> >+ >+ <a title="Move alert to top" href="audio_alerts.pl?action=move&where=top&id=[% a.id %]"> >+ <img src="[% interface %]/[% theme %]/img/go-top.png" border="0" alt="Go top" /> >+ </a> >+ >+ <a title="Move alert to bottom" href="audio_alerts.pl?action=move&where=bottom&id=[% a.id %]"> >+ <img src="[% interface %]/[% theme %]/img/go-bottom.png" border="0" alt="Go bottom" /> >+ </a> >+ >+ <a title="Move alert down" href="audio_alerts.pl?action=move&where=down&id=[% a.id %]"> >+ <img src="[% interface %]/[% theme %]/img/go-down.png" border="0" alt="Go down" /> >+ </a> >+ </td> >+ <td>[% a.selector %]</td> >+ <td>[% a.sound %]</td> >+ </tr> >+ [% END %] >+ </tbody> >+ </table> >+ >+ <p/> >+ <button id="delete-alerts" type="submit" class="btn"><i class="icon-trash"></i> Delete selected alerts</button> >+ </form> >+ </div> >+ </div> >+ <div class="yui-b"> >+[% INCLUDE 'admin-menu.inc' %] >+</div> >+</div> >+[% INCLUDE 'intranet-bottom.inc' %] >-- >1.7.2.5
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
|
Splinter Review
Attachments on
bug 11431
:
29030
|
29031
|
29032
|
29033
|
29034
|
29035
|
29036
|
29037
|
29038
|
29039
|
29119
|
29120
|
29404
|
29764
|
29765
|
29766
|
29767
|
29768
|
29769
|
31145
|
31146
|
31147
|
31148
|
31149
|
31150
|
34637
|
34638
|
34639
|
34640
|
34641
|
34642
|
34643
|
34644
|
34645
|
34646
|
34647
|
34648
|
34649
|
34650
|
34651
|
34652
|
34653
|
34717
|
34718
|
34719
|
34720
|
34864
|
34865
|
34866
|
34867
|
35843
|
35844
|
35845
|
35846
|
38547
|
38548
|
40726
|
40727
|
40728
|
40729
|
40730
|
40731
|
40732
|
41634
|
41661
|
41662
|
42678
|
42679
|
42680
|
42681
|
42682
|
42683
|
42684
|
42685
|
42686
|
42687
|
42688
|
42689
|
42696
|
43753
|
43754
|
43755
|
43756
|
43757
|
43758
|
43759
|
43760
|
43761
|
43762
|
43763
|
43764
|
43765
|
43817
|
43820
|
43821
|
43822
|
43823
|
43824
|
43825
|
43887
|
43888
|
43889
|
43890
|
43891
|
43892
|
43893
|
43894
|
43895
|
43896
|
43897
|
43898
|
43899
|
43900
|
43901
|
43902
|
43903
|
44391
|
44392
|
44393
|
44394
|
44395
|
44396
|
44397
|
44398
|
44399
|
44400
|
44401
|
44402
|
44404
|
44405
|
44407
|
44408
|
44409
|
44411
|
44412
|
44599
|
45135