|
| 1 | +import json |
| 2 | +import logging |
| 3 | +import os |
| 4 | +import getorg |
| 5 | + |
| 6 | +from data.models import Contributor |
| 7 | + |
| 8 | + |
| 9 | +def handle(output_dir='cluster_map'): |
| 10 | + """ |
| 11 | + Creates a organization cluster map using the contributors location |
| 12 | + stored in the database |
| 13 | + :param output_dir: Directory where all the required CSS and JS files |
| 14 | + are copied by 'getorg' package |
| 15 | + :return: None |
| 16 | + """ |
| 17 | + logger = logging.getLogger(__name__) |
| 18 | + |
| 19 | + logger.info('\'cluster_map/\' is the default directory for storing' |
| 20 | + ' organization map related files. If arg \'output_dir\'' |
| 21 | + ' not provided it will be used as a default directory by' |
| 22 | + ' \'getorg\' package.') |
| 23 | + |
| 24 | + # For creating the organization map, the 'getorg' uses a 'Nominatim' named |
| 25 | + # package which geocodes the contributor location and then uses that class |
| 26 | + # to create the map. Since, we're not dealing with that function which use |
| 27 | + # that 'Nominatim' package because we're fetching a JSON data and storing |
| 28 | + # it in our db. Therefore, defining our own simple class that can aid us |
| 29 | + # to create a cluster map. |
| 30 | + class Location: |
| 31 | + |
| 32 | + def __init__(self, longitude, latitude): |
| 33 | + self.longitude = longitude |
| 34 | + self.latitude = latitude |
| 35 | + |
| 36 | + org_location_dict = {} |
| 37 | + |
| 38 | + for contrib in Contributor.objects.all(): |
| 39 | + if not contrib.login.startswith('testuser') and contrib.location: |
| 40 | + user_location = json.loads(contrib.location) |
| 41 | + location = Location(user_location['longitude'], |
| 42 | + user_location['latitude']) |
| 43 | + org_location_dict[contrib.login] = location |
| 44 | + logger.debug('{} location {} added on map'.format( |
| 45 | + contrib.login, user_location)) |
| 46 | + getorg.orgmap.output_html_cluster_map(org_location_dict, |
| 47 | + folder_name=output_dir) |
| 48 | + |
| 49 | + move_and_make_changes_in_files(output_dir) |
| 50 | + |
| 51 | + |
| 52 | +def move_and_make_changes_in_files(output_dir): |
| 53 | + """ |
| 54 | + # Move static files from 'output_dir' to django static folder and |
| 55 | + # the 'map.html' file to django templates directory to get it displayed |
| 56 | + # on the homepage with the needed django syntax and CSS in the html file. |
| 57 | + :param output_dir: Directory from where the files have to be moved |
| 58 | + :return: None |
| 59 | + """ |
| 60 | + |
| 61 | + # Move leaflet_dist folder to static folder |
| 62 | + leaflet_source_path = '{}/{}/leaflet_dist/'.format(os.getcwd(), |
| 63 | + output_dir) |
| 64 | + leaflet_destination_path = '{}/{}/leaflet_dist/'.format(os.getcwd(), |
| 65 | + 'static') |
| 66 | + |
| 67 | + # Remove existing leaflet_dir if exists |
| 68 | + for root, dirs, files in os.walk(leaflet_destination_path): |
| 69 | + for file in files: |
| 70 | + os.remove(os.path.join(leaflet_destination_path, file)) |
| 71 | + os.rmdir(root) |
| 72 | + |
| 73 | + os.renames(leaflet_source_path, leaflet_destination_path) |
| 74 | + |
| 75 | + # Move org_locations.js to static folder |
| 76 | + locations_source_path = '{}/{}/org-locations.js'.format(os.getcwd(), |
| 77 | + output_dir) |
| 78 | + locations_destination_path = '{}/{}/org-locations.js'.format( |
| 79 | + os.getcwd(), 'static') |
| 80 | + os.rename(locations_source_path, locations_destination_path) |
| 81 | + |
| 82 | + # Make changes in map.html to support django syntax with needed CSS |
| 83 | + with open('{}/map.html'.format(output_dir)) as f: |
| 84 | + django_supported_htmls = [] |
| 85 | + lines = f.readlines() |
| 86 | + for index in range(len(lines)): |
| 87 | + line = lines[index].strip() |
| 88 | + if line.__contains__('<html>'): |
| 89 | + django_supported_htmls.append('{% load staticfiles %}\n') |
| 90 | + django_supported_htmls.append(line + '\n') |
| 91 | + elif line.__contains__('</head>'): |
| 92 | + adjust_prop = ''' |
| 93 | + <style> |
| 94 | + #map { |
| 95 | + width: 60%; |
| 96 | + height: 300px; |
| 97 | + margin: auto; |
| 98 | + box-shadow: 0px 0px 25px 2px; |
| 99 | + } |
| 100 | + @media only screen and (max-width:750px){ |
| 101 | + #map { |
| 102 | + width: 90% |
| 103 | + } |
| 104 | + } |
| 105 | + </style>\n |
| 106 | + ''' |
| 107 | + meta_charset = '<meta charset="utf-8">' |
| 108 | + adjust_prop = adjust_prop.strip().replace(' ', '') |
| 109 | + django_supported_htmls.insert(6, meta_charset + '\n') |
| 110 | + django_supported_htmls.append(adjust_prop + '\n') |
| 111 | + django_supported_htmls.append(line + '\n') |
| 112 | + elif line.__contains__('https://'): |
| 113 | + line = line.replace('https:', '').replace(' />', '>') |
| 114 | + django_supported_htmls.append(line.strip() + '\n') |
| 115 | + elif line.__contains__('<link '): |
| 116 | + line = line.replace('href="', 'href="{% static \'') |
| 117 | + line = line.replace('.css', '.css\' %}').replace(' />', '>') |
| 118 | + django_supported_htmls.append(line + '\n') |
| 119 | + elif line.__contains__('<script '): |
| 120 | + line = line.replace('src="', 'src="{% static \'') |
| 121 | + line = line.replace('.js', '.js\' %}') |
| 122 | + if line.__contains__(' type="text/javascript"'): |
| 123 | + line = line.replace(' type="text/javascript"', '') |
| 124 | + django_supported_htmls.append(line + '\n') |
| 125 | + elif line.__contains__('Mouse over') or len(line) == 0: |
| 126 | + pass |
| 127 | + else: |
| 128 | + django_supported_htmls.append(line + '\n') |
| 129 | + |
| 130 | + # Remove and Add 'map.html' to django templates directory |
| 131 | + html_map_path = '{}/{}/map.html' |
| 132 | + html_map_source_path = html_map_path.format(os.getcwd(), |
| 133 | + output_dir) |
| 134 | + html_map_destination_path = html_map_path.format(os.getcwd(), |
| 135 | + 'templates') |
| 136 | + os.remove(html_map_source_path) |
| 137 | + with open(html_map_destination_path, 'w+') as f: |
| 138 | + f.writelines(django_supported_htmls) |
0 commit comments