mirror of
				https://github.com/iiab/iiab.git
				synced 2025-03-09 15:40:17 +00:00 
			
		
		
		
	Osm (#26)
* fixes to change iiab->osm * change the name in meta too * create osm_install/enabled default flags * add maps alias,copy map.html to index.html * source file names do not change * incorporate osm-fixes in playbook * template rather than copy * add iiab back in for menu system
This commit is contained in:
		
							parent
							
								
									a4fb89ba35
								
							
						
					
					
						commit
						617dbde56f
					
				
					 11 changed files with 651 additions and 37 deletions
				
			
		| 
						 | 
				
			
			@ -1,6 +1,6 @@
 | 
			
		|||
dependencies:
 | 
			
		||||
   - { role: moodle, tags: ['olpc','moodle','edu-apps'], when: moodle_install }
 | 
			
		||||
   - { role: iiab, tags: ['iiab','edu-apps'], when: iiab_install }
 | 
			
		||||
   - { role: osm, tags: ['osm','edu-apps'], when: osm_install }
 | 
			
		||||
   - { role: pathagar, tags: ['pathagar','edu-apps'], when: pathagar_install }
 | 
			
		||||
   - { role: rachel, tags: ['rachel','edu-apps'], when: rachel_install }
 | 
			
		||||
   - { role: kalite, tags: ['kalite','edu-apps'], when: kalite_install }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,18 +0,0 @@
 | 
			
		|||
#IIAB Apache2 configuration file
 | 
			
		||||
 | 
			
		||||
XSendFile on
 | 
			
		||||
XSendFilePath /
 | 
			
		||||
 | 
			
		||||
WSGIScriptAlias /iiab {{ doc_root }}/iiab.wsgi
 | 
			
		||||
 | 
			
		||||
{% if is_debuntu %}
 | 
			
		||||
Alias /iiabstatic /usr/local/lib/python2.7/dist-packages/iiab/static
 | 
			
		||||
 | 
			
		||||
<Directory /usr/local/lib/python2.7/dist-packages/iiab/static>
 | 
			
		||||
{% else %}
 | 
			
		||||
Alias /iiabstatic /usr/lib/python2.7/site-packages/iiab/static
 | 
			
		||||
 | 
			
		||||
<Directory /usr/lib/python2.7/site-packages/iiab/static>
 | 
			
		||||
{% endif %}
 | 
			
		||||
	require all granted
 | 
			
		||||
</Directory>
 | 
			
		||||
							
								
								
									
										2
									
								
								roles/osm/defaults/main.yml
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								roles/osm/defaults/main.yml
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,2 @@
 | 
			
		|||
osm_install: True
 | 
			
		||||
osm_enabled: False
 | 
			
		||||
| 
						 | 
				
			
			@ -105,26 +105,26 @@
 | 
			
		|||
 | 
			
		||||
- name: Copy IIAB config file
 | 
			
		||||
  template: backup=yes
 | 
			
		||||
            src=iiab.conf.j2
 | 
			
		||||
            dest=/etc/{{ apache_config_dir }}/iiab.conf
 | 
			
		||||
            src=osm.conf.j2
 | 
			
		||||
            dest=/etc/{{ apache_config_dir }}/osm.conf
 | 
			
		||||
            owner=root
 | 
			
		||||
            group=root
 | 
			
		||||
            mode=0644
 | 
			
		||||
 | 
			
		||||
- name: Create a link from sites-enabled to sites-available
 | 
			
		||||
  file: src=/etc/apache2/sites-available/iiab.conf
 | 
			
		||||
        dest=/etc/apache2/sites-enabled/iiab.conf
 | 
			
		||||
  file: src=/etc/apache2/sites-available/osm.conf
 | 
			
		||||
        dest=/etc/apache2/sites-enabled/osm.conf
 | 
			
		||||
        state=link
 | 
			
		||||
  when: iiab_enabled and is_debuntu
 | 
			
		||||
  when: osm_enabled and is_debuntu
 | 
			
		||||
 | 
			
		||||
- name: Remove the link from sites-enabled to sites-available
 | 
			
		||||
  file: dest=/etc/apache2/sites-enabled/iiab.conf
 | 
			
		||||
  file: dest=/etc/apache2/sites-enabled/osm.conf
 | 
			
		||||
        state=absent
 | 
			
		||||
  when: not iiab_enabled and is_debuntu
 | 
			
		||||
  when: not osm_enabled and is_debuntu
 | 
			
		||||
 | 
			
		||||
- name: Create link to cgi
 | 
			
		||||
  file: src=/bin/iiab.wsgi
 | 
			
		||||
        dest={{ doc_root}}/iiab.wsgi
 | 
			
		||||
        dest={{ doc_root}}/osm.wsgi
 | 
			
		||||
        owner=root
 | 
			
		||||
        group=root
 | 
			
		||||
        state=link
 | 
			
		||||
| 
						 | 
				
			
			@ -132,7 +132,7 @@
 | 
			
		|||
 | 
			
		||||
- name: Create link to cgi
 | 
			
		||||
  file: src=/usr/local/bin/iiab.wsgi
 | 
			
		||||
        dest={{ doc_root }}/iiab.wsgi
 | 
			
		||||
        dest={{ doc_root }}/osm.wsgi
 | 
			
		||||
        owner=root
 | 
			
		||||
        group=root
 | 
			
		||||
        state=link
 | 
			
		||||
| 
						 | 
				
			
			@ -154,9 +154,28 @@
 | 
			
		|||
            dest=/usr/local/lib/python2.7/dist-packages/iiab/defaults.ini
 | 
			
		||||
  when: is_debuntu
 | 
			
		||||
 | 
			
		||||
- name: add iiab to service list
 | 
			
		||||
# the following was brought into OSM playbook from iiab-factory osm-fix script
 | 
			
		||||
- name: Get the path for python-redhat
 | 
			
		||||
  set_fact: python_path=/usr/lib/python2.7/site-packages/iiab
 | 
			
		||||
  when: is_redhat
 | 
			
		||||
 | 
			
		||||
- name: Get the path for python-debuntu
 | 
			
		||||
  set_fact: python_path=/usr/local/lib/python2.7/dist-packages/iiab
 | 
			
		||||
  when: is_debuntu
 | 
			
		||||
 | 
			
		||||
- name: Copy the files 
 | 
			
		||||
  template: src={{ item.src }} dest={{ item.dest }}
 | 
			
		||||
  with_items:
 | 
			
		||||
     - { src: 'etc.iiab.conf', dest: '/etc/iiab.conf' }
 | 
			
		||||
     - { src: 'map_search.py', dest: "{{ python_path }}/map_search.py" }
 | 
			
		||||
     - { src: 'map.html', dest: "{{ python_path }}/static/map.html" }
 | 
			
		||||
     - { src: 'l.control.geosearch.js', dest: "{{ python_path }}/static/lib/leaflet/geosearch/l.control.geosearch.js" }
 | 
			
		||||
#  end of imported osm-fix
 | 
			
		||||
     - { src: '{{ python_path }}/static/map.html', dest: "{{ python_path }}/static/index.html" }
 | 
			
		||||
 | 
			
		||||
- name: add osm to service list
 | 
			
		||||
  ini_file: dest='{{ service_filelist }}'
 | 
			
		||||
            section=iiab
 | 
			
		||||
            section=osm
 | 
			
		||||
            option='{{ item.option }}'
 | 
			
		||||
            value='{{ item.value }}'
 | 
			
		||||
  with_items:
 | 
			
		||||
| 
						 | 
				
			
			@ -165,6 +184,6 @@
 | 
			
		|||
    - option: description
 | 
			
		||||
      value: '"The Internet-in-a-Box is a small, inexpensive device which provides essential Internet resources without any Internet connection. It provides a local copy of half a terabyte of the world’s Free information."'
 | 
			
		||||
    - option: path
 | 
			
		||||
      value: /iiab
 | 
			
		||||
      value: /osm
 | 
			
		||||
    - option: enabled
 | 
			
		||||
      value: "{{ iiab_enabled }}"
 | 
			
		||||
      value: "{{ osm_enabled }}"
 | 
			
		||||
| 
						 | 
				
			
			@ -41,11 +41,11 @@ bin_dir = %(knowledge_dir)s/sys/bin-%(arch)s
 | 
			
		|||
[WEBAPP]
 | 
			
		||||
port = 25000
 | 
			
		||||
interface = 0.0.0.0
 | 
			
		||||
base_prefix = /iiab/
 | 
			
		||||
base_prefix = /osm/
 | 
			
		||||
use_x_sendfile = False
 | 
			
		||||
 | 
			
		||||
[ZIM]
 | 
			
		||||
url = /iiab/zim
 | 
			
		||||
url = /osm/zim
 | 
			
		||||
wikipedia_zim_dir = %(modules_dir)s/wikipedia-zim
 | 
			
		||||
wikipedia_index_dir = %(modules_dir)s/wikipedia-index
 | 
			
		||||
kiwix_library_file = %(wikipedia_zim_dir)s/library.xml
 | 
			
		||||
| 
						 | 
				
			
			@ -72,7 +72,7 @@ khan_cache_file = /tmp/khan_cache.json
 | 
			
		|||
; so they can be served directly by the front end web server
 | 
			
		||||
symlink_dir = %(khanacademy_dir)s/khanlinks
 | 
			
		||||
; This is static content, so it can change based on web server config
 | 
			
		||||
video_url = /iiab/video/khanvideo
 | 
			
		||||
video_url = /osm/video/khanvideo
 | 
			
		||||
 | 
			
		||||
[OSM]
 | 
			
		||||
openstreetmap_dir = %(modules_dir)s/openstreetmap
 | 
			
		||||
| 
						 | 
				
			
			@ -80,4 +80,4 @@ osm_search_dir = %(modules_dir)s/geonames_index
 | 
			
		|||
 | 
			
		||||
[SOFTWARE]
 | 
			
		||||
software_dir = %(modules_dir)s/ubuntu/12.04/mirror/archive.ubuntu.com/ubuntu
 | 
			
		||||
software_url = /iiab/software
 | 
			
		||||
software_url = /osm/software
 | 
			
		||||
							
								
								
									
										25
									
								
								roles/osm/templates/etc.iiab.conf
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								roles/osm/templates/etc.iiab.conf
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,25 @@
 | 
			
		|||
;; Local Configuration file for Internet-in-a-Box
 | 
			
		||||
;;
 | 
			
		||||
;;
 | 
			
		||||
;
 | 
			
		||||
;; [DEFAULT] is a special section.  Any settings there
 | 
			
		||||
;; will automatically appear in all other sections.
 | 
			
		||||
[DEFAULT]
 | 
			
		||||
; Location of our dataset
 | 
			
		||||
knowledge_dir = /library/knowledge
 | 
			
		||||
; repeat all the other assignments to get the new dir
 | 
			
		||||
processed_dir = %(knowledge_dir)s/processed
 | 
			
		||||
modules_dir = %(knowledge_dir)s/modules
 | 
			
		||||
data_dir = %(knowledge_dir)s/data
 | 
			
		||||
 | 
			
		||||
; If search_for_knowledge_dir is true, then
 | 
			
		||||
; the system will search all mounted volumes
 | 
			
		||||
; for a "knowledge/" directory if the path
 | 
			
		||||
; specified in knowledge_dir does not exist.
 | 
			
		||||
search_for_knowledge_dir = True
 | 
			
		||||
 | 
			
		||||
; Machine architecture.  This is set by the
 | 
			
		||||
; application at run-time.
 | 
			
		||||
arch = unset
 | 
			
		||||
bin_dir = %(knowledge_dir)s/sys/bin-%(arch)s
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										425
									
								
								roles/osm/templates/l.control.geosearch.js
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										425
									
								
								roles/osm/templates/l.control.geosearch.js
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,425 @@
 | 
			
		|||
/*
 | 
			
		||||
 * L.Control.GeoSearch - search for an address and zoom to it's location
 | 
			
		||||
 * https://github.com/smeijer/leaflet.control.geosearch
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
L.GeoSearch = {};
 | 
			
		||||
L.GeoSearch.Provider = {};
 | 
			
		||||
 | 
			
		||||
// MSIE needs cors support
 | 
			
		||||
jQuery.support.cors = true;
 | 
			
		||||
 | 
			
		||||
L.GeoSearch.Result = function (x, y, label) {
 | 
			
		||||
    this.X = x;
 | 
			
		||||
    this.Y = y;
 | 
			
		||||
    this.Label = label;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
L.Control.GeoSearch = L.Control.extend({
 | 
			
		||||
    options: {
 | 
			
		||||
        position: 'topcenter'
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    initialize: function (options) {
 | 
			
		||||
        this._config = {};
 | 
			
		||||
        L.Util.extend(this.options, options);
 | 
			
		||||
        this.setConfig(options);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    setConfig: function (options) {
 | 
			
		||||
        this._config = {
 | 
			
		||||
            'country': options.country || '',
 | 
			
		||||
            'provider': options.provider,
 | 
			
		||||
 | 
			
		||||
            'searchLabel': options.searchLabel || 'search for address...',
 | 
			
		||||
            'notFoundMessage' : options.notFoundMessage || 'Sorry, that address could not be found.',
 | 
			
		||||
            'messageHideDelay': options.messageHideDelay || 3000,
 | 
			
		||||
            'zoomLevel': options.zoomLevel || 18,
 | 
			
		||||
 | 
			
		||||
            'maxMarkers': options.maxMarkers || 1,
 | 
			
		||||
            'enableButtons': options.enableButtons || false,
 | 
			
		||||
 | 
			
		||||
            'enableAutocomplete': options.enableAutocomplete || false,
 | 
			
		||||
            'autocompleteMinQueryLen': options.autocompleteMinQueryLen || 3, // query length request threshold
 | 
			
		||||
            'autocompleteQueryDelay_ms': options.autocompleteQueryDelay_ms || 800
 | 
			
		||||
        };
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    onAdd: function (map) {
 | 
			
		||||
        var $controlContainer = $(map._controlContainer);
 | 
			
		||||
 | 
			
		||||
        if ($controlContainer.children('.leaflet-top.leaflet-center').length == 0) {
 | 
			
		||||
            $controlContainer.append('<div class="leaflet-top leaflet-center"></div>');
 | 
			
		||||
            map._controlCorners.topcenter = $controlContainer.children('.leaflet-top.leaflet-center').first()[0];
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this._map = map;
 | 
			
		||||
        this._container = L.DomUtil.create('div', 'leaflet-control-geosearch');
 | 
			
		||||
 | 
			
		||||
        var searchbox = document.createElement('input');
 | 
			
		||||
        searchbox.id = 'leaflet-control-geosearch-qry';
 | 
			
		||||
        searchbox.type = 'text';
 | 
			
		||||
        searchbox.placeholder = this._config.searchLabel;
 | 
			
		||||
        this._searchbox = searchbox;
 | 
			
		||||
        if (this._autocomplete) {
 | 
			
		||||
            this._autocomplete.recordLastUserInput('');
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (this._config.enableButtons) {
 | 
			
		||||
            var submitContainer = L.DomUtil.create('div', 'leaflet-control-geosearch-button-submit-container', this._container);
 | 
			
		||||
            L.DomUtil.create('span', 'leaflet-geosearch-submit-button', submitContainer);
 | 
			
		||||
            var cancelButton = L.DomUtil.create('span', 'leaflet-geosearch-cancel-button', this._container);
 | 
			
		||||
            L.DomEvent.on(submitContainer, 'click', this._submitRequest, this);
 | 
			
		||||
            L.DomEvent.on(cancelButton, 'click', this._clearUserSearchInput, this);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        var msgbox = document.createElement('div');
 | 
			
		||||
        msgbox.id = 'leaflet-control-geosearch-msg';
 | 
			
		||||
        msgbox.className = 'leaflet-control-geosearch-msg';
 | 
			
		||||
        this._msgbox = msgbox;
 | 
			
		||||
 | 
			
		||||
        var resultslist = document.createElement('ul');
 | 
			
		||||
        resultslist.id = 'leaflet-control-geosearch-results';
 | 
			
		||||
        this._resultslist = resultslist;
 | 
			
		||||
 | 
			
		||||
        $(this._msgbox).append(this._resultslist);
 | 
			
		||||
        $(this._container).append(this._searchbox, this._msgbox);
 | 
			
		||||
 | 
			
		||||
        if (this._config.enableAutocomplete) {
 | 
			
		||||
            this._autocomplete = new L.AutoComplete(this.options).addTo(this._container, function (suggestionText) {
 | 
			
		||||
                this._searchbox.value = suggestionText;
 | 
			
		||||
            }.bind(this));
 | 
			
		||||
            $(this._container).append(this._autocomplete);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // TODO This will result in duplicate processing of events. Options?
 | 
			
		||||
        L.DomEvent
 | 
			
		||||
          .addListener(this._container, 'click', L.DomEvent.stop)
 | 
			
		||||
          .addListener(this._container, 'keyup', this._onKeyUp, this)
 | 
			
		||||
          .addListener(this._container, 'change', this._onInputUpdate, this)
 | 
			
		||||
          .addListener(this._container, 'paste', this._onPasteToInput, this);
 | 
			
		||||
 | 
			
		||||
        L.DomEvent.disableClickPropagation(this._container);
 | 
			
		||||
 | 
			
		||||
        return this._container;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    geosearch: function (qry) {
 | 
			
		||||
        this.geosearch_ext(qry, this._processResults.bind(this), this._printError.bind(this));
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    geosearch_ext: function(qry, onSuccess, onFailure) {
 | 
			
		||||
        try {
 | 
			
		||||
            var provider = this._config.provider;
 | 
			
		||||
 | 
			
		||||
            if(typeof provider.GetLocations == 'function') {
 | 
			
		||||
                var results = provider.GetLocations(qry, function(results) {
 | 
			
		||||
                    onSuccess(results);
 | 
			
		||||
                }.bind(this));
 | 
			
		||||
            }
 | 
			
		||||
            else {
 | 
			
		||||
                var url = provider.GetServiceUrl(qry);
 | 
			
		||||
 | 
			
		||||
                $.getJSON(url, function (data) {
 | 
			
		||||
                    try {
 | 
			
		||||
                        var results = provider.ParseJSON(data);
 | 
			
		||||
                        onSuccess(results);
 | 
			
		||||
                    }
 | 
			
		||||
                    catch (error) {
 | 
			
		||||
                        onFailure(error);
 | 
			
		||||
                    }
 | 
			
		||||
                }.bind(this));
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        catch (error) {
 | 
			
		||||
            onFailure(error);
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    // qry may be a String or a function
 | 
			
		||||
    geosearch_autocomplete: function (qry, requestDelay_ms) {
 | 
			
		||||
        if (!this._config.enableAutocomplete) {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        clearTimeout(this._autocompleteRequestTimer);
 | 
			
		||||
 | 
			
		||||
        this._autocompleteRequestTimer = setTimeout(function () {
 | 
			
		||||
            var q = qry;
 | 
			
		||||
            if (typeof qry === 'function') {
 | 
			
		||||
                q = qry();
 | 
			
		||||
            }
 | 
			
		||||
            if (q.length >= this._config.autocompleteMinQueryLen) {
 | 
			
		||||
                this.geosearch_ext(q, this._autocomplete.show.bind(this._autocomplete), this._autocomplete.hide.bind(this._autocomplete));
 | 
			
		||||
            } else {
 | 
			
		||||
                this._autocomplete.hide();
 | 
			
		||||
            }
 | 
			
		||||
        }.bind(this), requestDelay_ms);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _processResults: function(results) {
 | 
			
		||||
        if (results.length == 0)
 | 
			
		||||
            throw this._config.notFoundMessage;
 | 
			
		||||
 | 
			
		||||
        this._map.fireEvent('geosearch_foundlocations', {Locations: results});
 | 
			
		||||
        this._showLocations(results);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _showLocations: function (results) {
 | 
			
		||||
        if (typeof this._layer !== 'undefined') {
 | 
			
		||||
            this._map.removeLayer(this._layer);
 | 
			
		||||
            this._layer = null;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this._markerList = []
 | 
			
		||||
        for (var ii=0; ii < results.length && ii < this._config.maxMarkers; ii++) {
 | 
			
		||||
            var location = results[ii];
 | 
			
		||||
            var marker = L.marker([location.Y, location.X]).bindPopup(location.Label);
 | 
			
		||||
            this._markerList.push(marker);
 | 
			
		||||
        }
 | 
			
		||||
        this._layer = L.layerGroup(this._markerList).addTo(this._map);
 | 
			
		||||
        this._printError('Displaying ' + Math.min(this._autocomplete._config.maxResultCount, results.length) + ' of ' + results.length +' results.');
 | 
			
		||||
 | 
			
		||||
        var premierResult = results[0];
 | 
			
		||||
        this._map.setView([premierResult.Y, premierResult.X], this._config.zoomLevel, false);
 | 
			
		||||
        this._map.fireEvent('geosearch_showlocation', {Location: premierResult});
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _printError: function(message) {
 | 
			
		||||
        $(this._resultslist)
 | 
			
		||||
            .html('<li>'+message+'</li>')
 | 
			
		||||
            .fadeIn('slow').delay(this._config.messageHideDelay).fadeOut('slow',
 | 
			
		||||
                    function () { $(this).html(''); });
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _submitRequest: function () {
 | 
			
		||||
        var q = $('#leaflet-control-geosearch-qry').val();
 | 
			
		||||
        if (q.length > 0) {
 | 
			
		||||
            this._hideAutocomplete();
 | 
			
		||||
            this.geosearch(q);
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _hideAutocomplete: function () {
 | 
			
		||||
        clearTimeout(this._autocompleteRequestTimer);
 | 
			
		||||
        if (this._config.enableAutocomplete && this._autocomplete.isVisible()) {
 | 
			
		||||
            this._autocomplete.hide();
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
        return false;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _clearUserSearchInput: function () {
 | 
			
		||||
        this._hideAutocomplete();
 | 
			
		||||
        $('#leaflet-control-geosearch-qry').val('');
 | 
			
		||||
        $('.leaflet-geosearch-cancel-button').hide();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onPasteToInput: function () {
 | 
			
		||||
        // onpaste requires callback to allow for input update do this by default.
 | 
			
		||||
        setTimeout(this._onInputUpdate.bind(this), 0);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onInputUpdate: function () {
 | 
			
		||||
        // define function for requery of user input after delay
 | 
			
		||||
        function getQuery() {
 | 
			
		||||
            return $('#leaflet-control-geosearch-qry').val();
 | 
			
		||||
        }
 | 
			
		||||
        var qry = getQuery();
 | 
			
		||||
 | 
			
		||||
        if (this._config.enableAutocomplete) {
 | 
			
		||||
            this._autocomplete.recordLastUserInput(qry);
 | 
			
		||||
            if (qry.length >= this._config.autocompleteMinQueryLen) {
 | 
			
		||||
                this.geosearch_autocomplete(getQuery, this._config.autocompleteQueryDelay_ms);
 | 
			
		||||
            } else {
 | 
			
		||||
                this._autocomplete.hide();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (qry.length > 0) {
 | 
			
		||||
            $('.leaflet-geosearch-cancel-button').show();
 | 
			
		||||
        } else {
 | 
			
		||||
            $('.leaflet-geosearch-cancel-button').hide();
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onKeyUp: function (e) {
 | 
			
		||||
        var REQ_DELAY_MS = 800;
 | 
			
		||||
        var MIN_AUTOCOMPLETE_LEN = 3;
 | 
			
		||||
        var enterKey = 13;
 | 
			
		||||
        var shift = 16;
 | 
			
		||||
        var ctrl = 17;
 | 
			
		||||
        var escapeKey = 27;
 | 
			
		||||
        var leftArrow = 37;
 | 
			
		||||
        var upArrow = 38;
 | 
			
		||||
        var rightArrow = 39;
 | 
			
		||||
        var downArrow = 40;
 | 
			
		||||
 | 
			
		||||
        switch (e.keyCode) {
 | 
			
		||||
            case escapeKey:
 | 
			
		||||
                // ESC first closes autocomplete if open. If closed then clears input.
 | 
			
		||||
                if (!this._hideAutocomplete()) {
 | 
			
		||||
                    this._clearUserSearchInput();
 | 
			
		||||
                }
 | 
			
		||||
                break;
 | 
			
		||||
            case enterKey:
 | 
			
		||||
                this._submitRequest();
 | 
			
		||||
                break;
 | 
			
		||||
            case upArrow:
 | 
			
		||||
                if (this._config.enableAutocomplete && this._autocomplete.isVisible()) {
 | 
			
		||||
                    this._autocomplete.moveUp();
 | 
			
		||||
                }
 | 
			
		||||
                break;
 | 
			
		||||
            case downArrow:
 | 
			
		||||
                if (this._config.enableAutocomplete && this._autocomplete.isVisible()) {
 | 
			
		||||
                    this._autocomplete.moveDown();
 | 
			
		||||
                }
 | 
			
		||||
                break;
 | 
			
		||||
            case leftArrow:
 | 
			
		||||
            case rightArrow:
 | 
			
		||||
            case shift:
 | 
			
		||||
            case ctrl:
 | 
			
		||||
                break;
 | 
			
		||||
            default:
 | 
			
		||||
                this._onInputUpdate();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
L.AutoComplete = L.Class.extend({
 | 
			
		||||
    initialize: function (options) {
 | 
			
		||||
        this._config = {};
 | 
			
		||||
        this.setConfig(options);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    setConfig: function (options) {
 | 
			
		||||
        this._config = {
 | 
			
		||||
            'maxResultCount': options.maxResultCount || 10,
 | 
			
		||||
            'onMakeSuggestionHTML': options.onMakeSuggestionHTML || function (geosearchResult) {
 | 
			
		||||
                return this._htmlEscape(geosearchResult.Label);
 | 
			
		||||
            }.bind(this),
 | 
			
		||||
        };
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    addTo: function (container, onSelectionCallback) {
 | 
			
		||||
        this._container = container;
 | 
			
		||||
        this._onSelection = onSelectionCallback;
 | 
			
		||||
        return this._createUI(container, 'leaflet-geosearch-autocomplete');
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    recordLastUserInput: function (str) {
 | 
			
		||||
        this._lastUserInput = str;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _createUI: function (container, className) {
 | 
			
		||||
        this._tool = L.DomUtil.create('div', className, container);
 | 
			
		||||
        this._tool.style.display = 'none';
 | 
			
		||||
        L.DomEvent
 | 
			
		||||
            .disableClickPropagation(this._tool)
 | 
			
		||||
            // consider whether to make delayed hide onBlur.
 | 
			
		||||
            // If so, consider canceling timer on mousewheel and mouseover.
 | 
			
		||||
            .on(this._tool, 'blur', this.hide, this)
 | 
			
		||||
            .on(this._tool, 'mousewheel', function(e) {
 | 
			
		||||
                L.DomEvent.stopPropagation(e); // to prevent map zoom
 | 
			
		||||
                if (e.axis === e.VERTICAL_AXIS) {
 | 
			
		||||
                    if (e.detail > 0) {
 | 
			
		||||
                        this.moveDown();
 | 
			
		||||
                    } else {
 | 
			
		||||
                        this.moveUp();
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }, this);
 | 
			
		||||
        return this;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    show: function (results) {
 | 
			
		||||
        this._tool.innerHTML = '';
 | 
			
		||||
        this._tool.currentSelection = -1;
 | 
			
		||||
        var count = 0;
 | 
			
		||||
        while (count < results.length && count < this._config.maxResultCount) {
 | 
			
		||||
            var entry = this._newSuggestion(results[count]);
 | 
			
		||||
            this._tool.appendChild(entry);
 | 
			
		||||
            ++count;
 | 
			
		||||
        }
 | 
			
		||||
        if (count > 0) {
 | 
			
		||||
            this._tool.style.display = 'block';
 | 
			
		||||
        } else {
 | 
			
		||||
            this.hide();
 | 
			
		||||
        }
 | 
			
		||||
        return count;
 | 
			
		||||
    },
 | 
			
		||||
    hide: function () {
 | 
			
		||||
        this._tool.style.display = 'none';
 | 
			
		||||
        this._tool.innerHTML = '';
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    isVisible: function() {
 | 
			
		||||
        return this._tool.style.display !== 'none';
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _htmlEscape: function (str) {
 | 
			
		||||
        // implementation courtesy of http://stackoverflow.com/a/7124052
 | 
			
		||||
        return String(str)
 | 
			
		||||
            .replace(/&/g, '&')
 | 
			
		||||
            .replace(/"/g, '"')
 | 
			
		||||
            .replace(/'/g, ''')
 | 
			
		||||
            .replace(/</g, '<')
 | 
			
		||||
            .replace(/>/g, '>');
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _newSuggestion: function (result) {
 | 
			
		||||
        var tip = L.DomUtil.create('li', 'leaflet-geosearch-suggestion');
 | 
			
		||||
        tip.innerHTML = this._config.onMakeSuggestionHTML(result);
 | 
			
		||||
        tip._text = result.Label;
 | 
			
		||||
        L.DomEvent
 | 
			
		||||
            .disableClickPropagation(tip)
 | 
			
		||||
            .on(tip, 'click', function(e) {
 | 
			
		||||
                this._onSelection(tip._text);
 | 
			
		||||
            }.bind(this), this);
 | 
			
		||||
        return tip;
 | 
			
		||||
    },
 | 
			
		||||
    _onSelectedUpdate: function () {
 | 
			
		||||
        var entries = this._tool.hasChildNodes() ? this._tool.childNodes : [];
 | 
			
		||||
        for (var ii=0; ii < entries.length; ++ii) {
 | 
			
		||||
            L.DomUtil.removeClass(entries[ii], 'leaflet-geosearch-suggestion-selected');
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // if selection is -1, then show last user typed text
 | 
			
		||||
        if (this._tool.currentSelection >= 0) {
 | 
			
		||||
            L.DomUtil.addClass(entries[this._tool.currentSelection], 'leaflet-geosearch-suggestion-selected');
 | 
			
		||||
 | 
			
		||||
            // scroll:
 | 
			
		||||
            var tipOffsetTop = entries[this._tool.currentSelection].offsetTop;
 | 
			
		||||
            if (tipOffsetTop + entries[this._tool.currentSelection].clientHeight >= this._tool.scrollTop + this._tool.clientHeight) {
 | 
			
		||||
                this._tool.scrollTop = tipOffsetTop - this._tool.clientHeight + entries[this._tool.currentSelection].clientHeight;
 | 
			
		||||
            }
 | 
			
		||||
            else if (tipOffsetTop <= this._tool.scrollTop) {
 | 
			
		||||
                this._tool.scrollTop = tipOffsetTop;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            this._onSelection(entries[this._tool.currentSelection]._text);
 | 
			
		||||
        } else {
 | 
			
		||||
            this._onSelection(this._lastUserInput);
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
    moveUp: function () {
 | 
			
		||||
        // permit selection to decrement down to -1 (none selected)
 | 
			
		||||
        if (this.isVisible() && this._tool.currentSelection >= 0) {
 | 
			
		||||
            --this._tool.currentSelection;
 | 
			
		||||
            this._onSelectedUpdate();
 | 
			
		||||
        }
 | 
			
		||||
        return this;
 | 
			
		||||
    },
 | 
			
		||||
    moveDown: function () {
 | 
			
		||||
        if (this.isVisible()) {
 | 
			
		||||
            this._tool.currentSelection = (this._tool.currentSelection + 1) % this.suggestionCount();
 | 
			
		||||
            this._onSelectedUpdate();
 | 
			
		||||
        }
 | 
			
		||||
        return this;
 | 
			
		||||
    },
 | 
			
		||||
    suggestionCount: function () {
 | 
			
		||||
        return this._tool.hasChildNodes() ? this._tool.childNodes.length : 0;
 | 
			
		||||
    },
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										79
									
								
								roles/osm/templates/map.html
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										79
									
								
								roles/osm/templates/map.html
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,79 @@
 | 
			
		|||
<!DOCTYPE html>
 | 
			
		||||
<html>
 | 
			
		||||
    <head>
 | 
			
		||||
        <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
 | 
			
		||||
        <link rel="stylesheet" href="lib/leaflet/leaflet.css" />
 | 
			
		||||
        <link rel="stylesheet" href="lib/leaflet/geosearch/l.geosearch.css" />
 | 
			
		||||
 | 
			
		||||
        <style type="text/css">
 | 
			
		||||
            body {
 | 
			
		||||
                padding: 0;
 | 
			
		||||
                margin: 0;
 | 
			
		||||
            }
 | 
			
		||||
            html, body, #map {
 | 
			
		||||
                height: 100%;
 | 
			
		||||
            }
 | 
			
		||||
        </style>
 | 
			
		||||
 | 
			
		||||
        <script type="text/javascript">
 | 
			
		||||
        // Required for Firefox 3.6
 | 
			
		||||
        if (!Function.prototype.bind) {
 | 
			
		||||
          Function.prototype.bind = function (oThis) {
 | 
			
		||||
            if (typeof this !== "function") {
 | 
			
		||||
              // closest thing possible to the ECMAScript 5 internal IsCallable function
 | 
			
		||||
              throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable");
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            var aArgs = Array.prototype.slice.call(arguments, 1),
 | 
			
		||||
                fToBind = this,
 | 
			
		||||
                fNOP = function () {},
 | 
			
		||||
                fBound = function () {
 | 
			
		||||
                  return fToBind.apply(this instanceof fNOP && oThis
 | 
			
		||||
                                         ? this
 | 
			
		||||
                                         : oThis,
 | 
			
		||||
                                       aArgs.concat(Array.prototype.slice.call(arguments)));
 | 
			
		||||
                };
 | 
			
		||||
 | 
			
		||||
            fNOP.prototype = this.prototype;
 | 
			
		||||
            fBound.prototype = new fNOP();
 | 
			
		||||
 | 
			
		||||
            return fBound;
 | 
			
		||||
          };
 | 
			
		||||
        }
 | 
			
		||||
        </script>
 | 
			
		||||
 | 
			
		||||
        <script src="lib/jquery-1.9.0.js"></script>
 | 
			
		||||
        <script src="lib/leaflet/leaflet.js"></script>
 | 
			
		||||
        <script src="lib/leaflet/geosearch/l.control.geosearch.js"></script>
 | 
			
		||||
        <script src="lib/leaflet/geosearch/l.geosearch.provider.iiab.js"></script>
 | 
			
		||||
 | 
			
		||||
        <script type="text/javascript">
 | 
			
		||||
            $(function () {
 | 
			
		||||
                var map = L.map('map'); /*.setView([51.505, -0.09], 14);*/
 | 
			
		||||
                L.tileLayer('/iiab/maps/tile/{z}/{x}/{y}.png', {
 | 
			
		||||
                    attribution: 'Map data © <a href="http://openstreetmap.org">OpenStreetMap</a> contributors, <a href="http://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>',
 | 
			
		||||
                    maxZoom: 15
 | 
			
		||||
                }).addTo(map);
 | 
			
		||||
 | 
			
		||||
                var geoOptions = {
 | 
			
		||||
                    provider: new L.GeoSearch.Provider.iiab(),
 | 
			
		||||
                    searchLabel: "Search by City Name...",
 | 
			
		||||
                    notFoundMessage: "No matches found",
 | 
			
		||||
                    zoomLevel: 8,
 | 
			
		||||
                    maxMarkers: 10,
 | 
			
		||||
                    maxResultCount: 15,
 | 
			
		||||
                    enableAutocomplete: true,
 | 
			
		||||
                    enableButtons: true
 | 
			
		||||
                };
 | 
			
		||||
                new L.Control.GeoSearch(geoOptions).addTo(map);
 | 
			
		||||
 | 
			
		||||
                map.fitWorld().setZoom(3);  // default world view
 | 
			
		||||
                //map.locate({setView: true, maxZoom: 15});
 | 
			
		||||
            });
 | 
			
		||||
        </script>
 | 
			
		||||
    </head>
 | 
			
		||||
    <body>
 | 
			
		||||
        <div id="map"></div>
 | 
			
		||||
 | 
			
		||||
    </body>
 | 
			
		||||
</html>
 | 
			
		||||
							
								
								
									
										58
									
								
								roles/osm/templates/map_search.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										58
									
								
								roles/osm/templates/map_search.py
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,58 @@
 | 
			
		|||
# Internet-in-a-Box System
 | 
			
		||||
# By Braddock Gaskill, 16 Feb 2013
 | 
			
		||||
# Modified by Tim Moody, 8 Apr 2016
 | 
			
		||||
from utils import whoosh_open_dir_32_or_64
 | 
			
		||||
# from whoosh.qparser import QueryParser
 | 
			
		||||
from whoosh.qparser import MultifieldParser
 | 
			
		||||
from whoosh import sorting
 | 
			
		||||
 | 
			
		||||
from utils import whoosh2dict
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class MapSearch(object):
 | 
			
		||||
    def __init__(self, index_dir):
 | 
			
		||||
        """Initialize a search object.
 | 
			
		||||
        index_dir is the Whoosh index directory to use."""
 | 
			
		||||
        self.index_dir = index_dir
 | 
			
		||||
 | 
			
		||||
    def search(self, query, page=1, pagelen=20):
 | 
			
		||||
        """Return a sorted list of results.
 | 
			
		||||
        pagelen specifies the number of hits per page.
 | 
			
		||||
        page specifies the page of results to return (first page is 1)
 | 
			
		||||
        Set pagelen = None or 0 to retrieve all results.
 | 
			
		||||
        """
 | 
			
		||||
        query = unicode(query)  # Must be unicode
 | 
			
		||||
        population_sort_facet = sorting.FieldFacet("population", reverse=True)
 | 
			
		||||
        ix = whoosh_open_dir_32_or_64(self.index_dir)
 | 
			
		||||
        with ix.searcher() as searcher:
 | 
			
		||||
            # query = QueryParser("ngram_name", ix.schema).parse(query)
 | 
			
		||||
            mparser = MultifieldParser(["ngram_name", "admin1_code", "country_code"], schema=ix.schema)
 | 
			
		||||
            query = mparser.parse(query)
 | 
			
		||||
            if pagelen is not None and pagelen != 0:
 | 
			
		||||
                try:
 | 
			
		||||
                    results = searcher.search_page(query, page, pagelen=pagelen)
 | 
			
		||||
                except ValueError, e:  # Invalid page number
 | 
			
		||||
                    results = []
 | 
			
		||||
            else:
 | 
			
		||||
                results = searcher.search(query, limit=None)
 | 
			
		||||
            #r = [x.items() for x in results]
 | 
			
		||||
            r = whoosh2dict(results)
 | 
			
		||||
        ix.close()
 | 
			
		||||
        # experiment with tucking away content for display in popup.
 | 
			
		||||
        print r
 | 
			
		||||
        for d in r:
 | 
			
		||||
            d['popupText'] = 'test content'
 | 
			
		||||
            d['name'] = d['name'] + ', ' + d['admin1_code'] + ', ' + d['country_code']
 | 
			
		||||
 | 
			
		||||
        return r
 | 
			
		||||
 | 
			
		||||
    def count(self, query):
 | 
			
		||||
        """Return total number of matching documents in index"""
 | 
			
		||||
        query = unicode(query)  # Must be unicode
 | 
			
		||||
        ix = whoosh_open_dir_32_or_64(self.index_dir)
 | 
			
		||||
        with ix.searcher() as searcher:
 | 
			
		||||
            query = QueryParser("title", ix.schema).parse(query)
 | 
			
		||||
            results = searcher.search(query)
 | 
			
		||||
            n = len(results)
 | 
			
		||||
        ix.close()
 | 
			
		||||
        return n
 | 
			
		||||
							
								
								
									
										24
									
								
								roles/osm/templates/osm.conf.j2
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								roles/osm/templates/osm.conf.j2
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,24 @@
 | 
			
		|||
#IIAB Apache2 configuration file
 | 
			
		||||
 | 
			
		||||
XSendFile on
 | 
			
		||||
XSendFilePath /
 | 
			
		||||
 | 
			
		||||
WSGIScriptAlias /osm {{ doc_root }}/osm.wsgi
 | 
			
		||||
 | 
			
		||||
{% if is_debuntu %}
 | 
			
		||||
Alias /iiabstatic /usr/local/lib/python2.7/dist-packages/iiab/static
 | 
			
		||||
Alias /osm /usr/local/lib/python2.7/dist-packages/iiab/static
 | 
			
		||||
Alias /maps /usr/local/lib/python2.7/dist-packages/iiab/static
 | 
			
		||||
Alias /iiab /usr/local/lib/python2.7/dist-packages/iiab/static
 | 
			
		||||
 | 
			
		||||
<Directory /usr/local/lib/python2.7/dist-packages/iiab/static>
 | 
			
		||||
{% else %}
 | 
			
		||||
Alias /iiabstatic /usr/lib/python2.7/site-packages/iiab/static
 | 
			
		||||
Alias /osm /usr/lib/python2.7/site-packages/iiab/static
 | 
			
		||||
Alias /maps /usr/lib/python2.7/site-packages/iiab/static
 | 
			
		||||
Alias /iiab /usr/lib/python2.7/site-packages/iiab/static
 | 
			
		||||
 | 
			
		||||
<Directory /usr/lib/python2.7/site-packages/iiab/static>
 | 
			
		||||
{% endif %}
 | 
			
		||||
	require all granted
 | 
			
		||||
</Directory>
 | 
			
		||||
| 
						 | 
				
			
			@ -1,4 +1,4 @@
 | 
			
		|||
[iiab]
 | 
			
		||||
[osm]
 | 
			
		||||
name=Internet-in-a-Box
 | 
			
		||||
baseurl=http://downloads.internet-in-a-box.org/fedora/18
 | 
			
		||||
enabled=1
 | 
			
		||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue