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

(-)a/api/api-google-places.pl (+43 lines)
Line 0 Link Here
1
#!/usr/bin/perl
2
3
use strict; use warnings;
4
use LWP::Simple;
5
use LWP::UserAgent;
6
use HTTP::Request::Common;
7
use C4::Context;
8
use CGI qw ( -utf8 );
9
use CGI::Session;
10
11
my $cgi = CGI->new;
12
my $session = CGI::Session->new();
13
if (defined $cgi->param("lang") && $cgi->param("lang") != "default"){
14
    $session->param(-name=>'lang', -value=>$cgi->param("lang"));
15
} else {
16
    $session->param(-name=>'lang', -value=>"en-CA");
17
}
18
$session->expire('+1h');
19
my $res = _fetch_content_API_Google_Map($session->param("lang"));
20
21
print $cgi->header(
22
    -title  => 'Google API Place',
23
    -type => "text/javascript",
24
    -script => {
25
        -type => "text/javascript",
26
        -code => $res->{'_content'}
27
    }
28
);
29
30
print $res->{'_content'};
31
32
sub _fetch_content_API_Google_Map {
33
    my ( $lang) = @_;
34
    my $key = C4::Context->preference('GooglePlacesAPI');    
35
    my $url = "https://maps.googleapis.com/maps/api/js?key=${key}&libraries=places&region=CA&language=${lang}";
36
    my $ua = LWP::UserAgent->new;
37
    $ua->timeout(10);
38
    $ua->env_proxy;
39
    my $response = $ua->get($url);
40
    warn "could not retrieve $url" unless $response->content;
41
    return $response;
42
}
43
1;
(-)a/installer/data/mysql/atomicupdate/bug_27379_autocomplete_addresses_google_api.perl (+8 lines)
Line 0 Link Here
1
$DBversion = 'XXX'; # will be replaced by the RM
2
if( CheckVersion( $DBversion ) ) {
3
    # you can use $dbh here like:
4
    $dbh->do(q{INSERT IGNORE INTO systempreferences (variable,value,options,explanation,type) VALUES ('GooglePlacesAPI', '', NULL, NULL, 'Free')});
5
6
    # Always end with this (adjust the bug info)
7
    NewVersion( $DBversion, 27379, "Autocomplete addresses using Google Places (Maps).");
8
}
(-)a/installer/data/mysql/mandatory/sysprefs.sql (-1 / +2 lines)
Lines 722-726 INSERT INTO systempreferences ( `variable`, `value`, `options`, `explanation`, ` Link Here
722
('XSLTListsDisplay','default','','Enable XSLT stylesheet control over lists pages display on intranet','Free'),
722
('XSLTListsDisplay','default','','Enable XSLT stylesheet control over lists pages display on intranet','Free'),
723
('XSLTResultsDisplay','default','','Enable XSL stylesheet control over results page display on intranet','Free'),
723
('XSLTResultsDisplay','default','','Enable XSL stylesheet control over results page display on intranet','Free'),
724
('z3950AuthorAuthFields','701,702,700',NULL,'Define the MARC biblio fields for Personal Name Authorities to fill biblio.author','free'),
724
('z3950AuthorAuthFields','701,702,700',NULL,'Define the MARC biblio fields for Personal Name Authorities to fill biblio.author','free'),
725
('z3950NormalizeAuthor','0','','If ON, Personal Name Authorities will replace authors in biblio.author','YesNo')
725
('z3950NormalizeAuthor','0','','If ON, Personal Name Authorities will replace authors in biblio.author','YesNo'),
726
('GooglePlacesAPI', '', 'This key must be obtained at https://developers.google.com/places/web-service/get-api-key.', NULL, 'Free')
726
;
727
;
(-)a/koha-tmpl/intranet-tmpl/js/api-google-places.js (+252 lines)
Line 0 Link Here
1
function GoogleMapsInitIntranet(){
2
       /* Pages pour API GOOGLE*/
3
       var affectedPages = ['memberentry', 'supplier', 'branches', 'cities'];
4
5
       /* page memberentry Adresse principale   */
6
       var inputs_memberenty_main = ['streetnumber', 'address', 'city', 'state', 'zipcode'];
7
       var page_memberenty_main_input = 'address';
8
       /* page memberentry Autre adresse   */
9
       var inputs_memberenty_alternate = ['B_streetnumber', 'B_address', 'B_city', 'B_state', 'B_country', 'B_zipcode'];
10
       var page_memberenty_alternate_input = 'B_address';
11
       /* page memberentry Autre contact */ 
12
       var inputs_memberenty_contact = ['altcontactaddress1', 'altcontactcity', 'altcontactstate', 'altcontactzipcode'];
13
       var page_memberenty_contact_input = 'altcontactaddress1';
14
       /* page supplier Adresse postale*/ 
15
       var page_supplier_input1 = 'company_postal';
16
       /* page supplier Adresse physique*/ 
17
       var page_supplier_input2 = 'physical';
18
       /* page supplier ranches */ 
19
       var inputs_branches = ['branchaddress1', 'branchcity', 'branchstate', 'branchcountry', 'branchzip'];
20
       var page_branches_input = 'branchaddress1';
21
       /* page cities */ 
22
       var inputs_cities = ['city_name', 'city_state', 'city_country', 'city_zipcode'];
23
       var page_cities_input = 'city_name';
24
   
25
       // Si on tombe sur une de ces pages
26
       if (affectedPages.indexOf(getPageName()) >= 0) {
27
   
28
           //Dictionaire pour comparer notre form (input->id) avec type API Google 
29
           var builder_dictionary = {
30
           /* form_input_id  :    type_google */
31
               /* page memberentry Adresse principale   */
32
               'streetnumber' : ['street_number'],
33
               'address' : ['route'],
34
               'city' : ['locality'],
35
               'state' :  ['administrative_area_level_1'],
36
               'zipcode' : ['postal_code'],
37
               /* page memberentry Autre adresse   */
38
               'B_streetnumber' : ['street_number'],
39
               'B_address' : ['route'],
40
               'B_city' : ['locality'],
41
               'B_state' :  ['administrative_area_level_1'],
42
               'B_zipcode' : ['postal_code'],
43
               /* page memberentry Autre contact */ 
44
               'altcontactaddress1' : ['street_number','route'],
45
               'delimiter_altcontactaddress1' : ', ',
46
               'altcontactcity' : ['locality'],
47
               'altcontactstate' : ['administrative_area_level_1'],
48
               'altcontactzipcode' :  ['postal_code']
49
           };        
50
   
51
           // Format de sortie composantes d'une adresse Google Maps pour notre form
52
           var format_api_google = {
53
               'street_number': 'short_name',
54
               'route': 'long_name',
55
               'locality': 'long_name',
56
               'administrative_area_level_1': 'short_name',
57
               'country': 'long_name',
58
               'postal_code': 'short_name',
59
               'postal_code_prefix': 'short_name'
60
           };
61
   
62
           /* Pages avec les champes pour changer */
63
           function initAutocomplete() {
64
               /* Option pour Autocomplete de Google */
65
               var t = 0;
66
               options = {
67
                   types: ['geocode'],
68
                   // Localisation de départ près de Montréal pour une recherch
69
                   // plus efficace si la géolocalisation est désactivée
70
                   bounds: new google.maps.LatLngBounds(
71
                       new google.maps.LatLng(45.5053543, -73.733018),
72
                   ),
73
                   componentRestrictions: {country: ['us', 'ca']}
74
               };
75
               /* Verifier une page */ 
76
               switch (getPageName()) {
77
                   case 'memberentry':
78
                       initAutocompleteMemberentry();
79
                       break;
80
                   case 'supplier':
81
                       initAutocompleteSupplier();
82
                       break;
83
                   case 'branches':
84
                       initAutocompleteBranches();
85
                       break;
86
                   case 'cities':
87
                       initAutocompleteCities();
88
                       break;
89
                   default:
90
                       console.log ("This page is " + page);
91
                       break;
92
               }               
93
           };
94
   
95
           /* page memberentry */
96
           function initAutocompleteMemberentry(){
97
               /* Adresse principale */
98
               primaryAutocomplete = new google.maps.places.Autocomplete(
99
               /** @type {!HTMLInputElement} */(document.getElementById(page_memberenty_main_input)), options);
100
               // Remplir les champs lorsque l'utilisateur a choisi l'adresse
101
               primaryAutocomplete.addListener('place_changed', 
102
                   function () {
103
                       fillInAddress(primaryAutocomplete, inputs_memberenty_main);
104
                   }
105
               );                
106
               $('#'+page_memberenty_main_input).focus(
107
                   function () { 
108
                       primaryAutocomplete
109
                   }
110
               );
111
               /* Autre adresse */
112
               B_autocomplete = new google.maps.places.Autocomplete(
113
                   /** @type {!HTMLInputElement} */(document.getElementById(page_memberenty_alternate_input)), options);
114
               B_autocomplete.addListener('place_changed', 
115
                   function () {
116
                       fillInAddress(B_autocomplete, inputs_memberenty_alternate);
117
                   }
118
               );
119
               $('#'+page_memberenty_alternate_input).focus(
120
                   function () { 
121
                       B_autocomplete;
122
                   }
123
               ); 
124
               /* Autre contact */
125
               altcontactaddress1 = new google.maps.places.Autocomplete(
126
                   /** @type {!HTMLInputElement} */(document.getElementById(page_memberenty_contact_input)), options);
127
               altcontactaddress1.addListener('place_changed', 
128
                   function () {
129
                       fillInAddress(altcontactaddress1, inputs_memberenty_contact);
130
                   }
131
               );
132
               $('#'+page_memberenty_contact_input).focus(
133
                   function () { 
134
                       B_autocomplete;
135
                   }
136
               ); 
137
           }
138
           
139
           /* page branches */
140
           function initAutocompleteBranches(){
141
               branchAutocomplete = new google.maps.places.Autocomplete(
142
                       /** @type {!HTMLInputElement} */(document.getElementById(page_branches_input)), options);
143
               branchAutocomplete.addListener('place_changed', 
144
                   function () {
145
                       fillInAddress(branchAutocomplete, inputs_branches);
146
                   }
147
               );
148
               $('#'+page_branches_input).focus(
149
                   function () { 
150
                       branchAutocomplete 
151
                   }
152
               );   
153
           }
154
           
155
           /* page cities */
156
           function initAutocompleteCities(){
157
               componentPlace = page_cities;
158
               cityTownAutocomplete = new google.maps.places.Autocomplete(
159
               /** @type {!HTMLInputElement} */(document.getElementById(page_cities_input)), options);
160
               cityTownAutocomplete.addListener('place_changed', 
161
                   function () {
162
                       fillInAddress(cityTownAutocomplete, inputs_cities);
163
                   }
164
               );
165
               $('#'+page_cities_input).focus(
166
                   function () { 
167
                       cityTownAutocomplete 
168
                   }
169
               );    
170
           }
171
   
172
           /* page supplier */
173
           function initAutocompleteSupplier(){
174
               postalAutocomplete = new google.maps.places.Autocomplete(
175
                   /** @type {!HTMLInputElement} */(document.getElementById(page_supplier_input1)), options);
176
               physicalAutocomplete = new google.maps.places.Autocomplete(
177
                   /** @type {!HTMLInputElement} */(document.getElementById(page_supplier_input2)), options);  
178
               $('#'+page_supplier_input1).focus(
179
                   function () { 
180
                       postalAutocomplete;
181
                   }
182
               );
183
               $('#'+page_supplier_input2).focus(
184
                   function () { 
185
                       physicalAutocomplete; 
186
                   }
187
               ); 
188
           }
189
   
190
           function fillInAddress(autocomplete, componentPlace) {
191
               //new 
192
               // Obtenir les infos de l'adresse
193
               let place = autocomplete.getPlace();
194
               
195
               //Verifier notre dictionaire
196
               for (let i = 0; i < componentPlace.length; i++) 
197
               {
198
                   if (componentPlace[i] != null && document.getElementById(componentPlace[i]) != null) 
199
                   {
200
                       let form_input_id = ''; 
201
                       CompPlace = document.getElementById(componentPlace[i]);
202
                       CompPlace.value = '';
203
   
204
                       form_input_id = Object.keys(builder_dictionary).find(key => key === componentPlace[i]);
205
                       let type_google = builder_dictionary[form_input_id];
206
                       switch (type_google.length) {
207
                           case 1:
208
                               for (let j = 0; j < place.address_components.length; j++) {
209
                                   if (type_google[0] == place.address_components[j].types[0]){
210
                                   CompPlace.value = place.address_components[j][format_api_google[type_google[0]]];
211
                                   }
212
                               }
213
                               break;
214
                           default:
215
                               var str_output = '';
216
                               var delimit = 'delimiter_' + form_input_id;
217
                               for (let b = 0; b < type_google.length; b++) {
218
                                   for (let j = 0; j < place.address_components.length; j++) {
219
                                       if (type_google[b] == place.address_components[j].types[0]){
220
                                           str_output += place.address_components[j][format_api_google[type_google[b]]] + builder_dictionary[delimit];
221
                                       }                                    
222
                                   }
223
                               }
224
                               str_output = str_output.slice(0, -Math.abs(builder_dictionary[delimit].length));
225
                               CompPlace.value = str_output;
226
                           break;
227
                       }
228
                   }
229
               }
230
           }
231
   
232
           // Chercher le script de l'API
233
           jQuery.ajax({
234
               url: '/cgi-bin/koha/api/api-google-places.pl?lang=' + $('html').attr('lang'),
235
               dataType: 'script',
236
               success: initAutocomplete,
237
               async: true,
238
               defer: true
239
           });
240
       }
241
   
242
       //Retourne le nom de la page sans extension et paramètres
243
       function getPageName() {
244
           var url = window.location.pathname;
245
           var index = url.lastIndexOf("/") + 1;
246
           var pageNameWithExtension = url.substr(index);
247
           var pageName = pageNameWithExtension.split(".")[0];
248
           return pageName;
249
       }
250
}
251
252
GoogleMapsInitIntranet();
(-)a/koha-tmpl/intranet-tmpl/prog/en/includes/js_includes.inc (+3 lines)
Lines 143-147 Link Here
143
        }
143
        }
144
    });
144
    });
145
    </script>
145
    </script>
146
[% IF ( Koha.Preference('GooglePlacesAPI').length  > 10) %]
147
    [% Asset.js("js/api-google-places.js") %]
148
[% END %]
146
[% END %]
149
[% END %]
147
<!-- / js_includes.inc -->
150
<!-- / js_includes.inc -->
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/patrons.pref (-1 / +6 lines)
Lines 379-381 Patrons: Link Here
379
             location: "Location"
379
             location: "Location"
380
             itemcallnumber: "Item's callnumber"
380
             itemcallnumber: "Item's callnumber"
381
             ccode: "Collection code"
381
             ccode: "Collection code"
382
- 
382
     -
383
         - Autocomplete addresses using Google Places (Maps).<br/>
384
         - Places API key Google
385
         - pref: GooglePlacesAPI
386
         - Can be obtained at https://developers.google.com/places/web-service/get-api-key.
387
     -

Return to bug 27379