Skip to content
Permalink
Browse files

[Fixes #3684] Keep original projection and BBOX / general cleanup of …

…resource models and logs
  • Loading branch information...
afabiani committed Mar 30, 2018
1 parent 1669a88 commit 0551910225aecdeb17cc26dfedfc508c72b0fc10
Showing with 1,143 additions and 580 deletions.
  1. +33 −0 geonode/api/resourcebase_api.py
  2. +5 −1 geonode/base/autocomplete_light_registry.py
  3. +1 −0 geonode/base/forms.py
  4. +24 −0 geonode/base/migrations/0033_auto_20180330_0951.py
  5. +37 −27 geonode/base/models.py
  6. +14 −1 geonode/base/templates/base/_resourcebase_snippet.html
  7. +5 −2 geonode/base/utils.py
  8. +1 −1 geonode/catalogue/templates/catalogue/full_metadata.xml
  9. +9 −1 geonode/client/hooks.py
  10. +14 −17 geonode/client/templates/geoext/layers/layer_geoext_map.html
  11. +14 −17 geonode/client/templates/geoext/layers/layer_geoext_map_mini.html
  12. +15 −19 geonode/client/templates/geoext/maps/map_geoexplorer.js
  13. +1 −1 geonode/documents/models.py
  14. +16 −14 geonode/documents/renderers.py
  15. +3 −0 geonode/documents/tasks.py
  16. +2 −1 geonode/documents/tests.py
  17. +2 −0 geonode/documents/views.py
  18. +5 −4 geonode/geoserver/helpers.py
  19. +12 −9 geonode/geoserver/signals.py
  20. +1 −1 geonode/geoserver/upload.py
  21. +3 −0 geonode/groups/tests.py
  22. +0 −1 geonode/groups/views.py
  23. +1 −1 geonode/invitations/forms.py
  24. +1 −1 geonode/invitations/views.py
  25. +2 −1 geonode/layers/models.py
  26. +1 −1 geonode/layers/tasks.py
  27. +1 −0 geonode/layers/templates/layers/layer_detail.html
  28. +1 −1 geonode/layers/templates/layers/layer_style_manage.html
  29. +10 −3 geonode/layers/tests.py
  30. +5 −4 geonode/layers/urls.py
  31. +67 −43 geonode/layers/utils.py
  32. +161 −38 geonode/layers/views.py
  33. +3 −3 geonode/local_settings.py.geoserver.sample
  34. +4 −1 geonode/local_settings.py.qgis.sample
  35. +6 −3 geonode/maps/models.py
  36. +2 −1 geonode/maps/tests.py
  37. +4 −4 geonode/maps/tests_populate_maplayers.py
  38. +2 −4 geonode/maps/urls.py
  39. +5 −2 geonode/maps/utils.py
  40. +34 −17 geonode/maps/views.py
  41. +12 −12 geonode/messaging/consumer.py
  42. +2 −2 geonode/messaging/management/commands/runmessaging.py
  43. +1 −1 geonode/notifications_helper.py
  44. +3 −3 geonode/people/admin.py
  45. +53 −12 geonode/proxy/views.py
  46. +80 −72 geonode/qgis_server/helpers.py
  47. +1 −1 geonode/qgis_server/models.py
  48. +6 −2 geonode/qgis_server/signals.py
  49. +4 −3 geonode/qgis_server/tests/test_helpers.py
  50. +30 −31 geonode/qgis_server/tests/test_views.py
  51. +59 −28 geonode/qgis_server/views.py
  52. +1 −7 geonode/security/utils.py
  53. +21 −3 geonode/services/enumerations.py
  54. +2 −1 geonode/services/forms.py
  55. +19 −0 geonode/services/migrations/0036_auto_20180331_1039.py
  56. +17 −12 geonode/services/models.py
  57. +8 −5 geonode/services/serviceprocessors/wms.py
  58. +1 −1 geonode/services/tests.py
  59. +13 −2 geonode/settings.py
  60. +13 −1 geonode/social/signals.py
  61. +1 −1 geonode/social/templatetags/social_tags.py
  62. +2 −2 geonode/static/geonode/js/extjs/GeoNode-GeoExplorer.js
  63. +2 −2 geonode/tests/bdd/conftest.py
  64. +4 −10 geonode/tests/integration.py
  65. +7 −1 geonode/tests/utils.py
  66. +3 −3 geonode/upload/tests/integration.py
  67. +7 −7 geonode/upload/upload.py
  68. +1 −1 geonode/upload/upload_validators.py
  69. +7 −6 geonode/upload/utils.py
  70. +1 −1 geonode/upload/views.py
  71. +5 −2 geonode/urls.py
  72. +212 −87 geonode/utils.py
  73. +2 −3 pavement.py
  74. +10 −7 requirements.txt
  75. +6 −3 setup.py
@@ -113,13 +113,29 @@ class CommonModelApi(ModelResource):
'uuid',
'title',
'date',
'date_type',
'edition',
'purpose',
'maintenance_frequency',
'restriction_code_type',
'constraints_other',
'license',
'language',
'spatial_representation_type',
'temporal_extent_start',
'temporal_extent_end',
'data_quality_statement',
'abstract',
'csw_wkt_geometry',
'csw_type',
'owner__username',
'share_count',
'popular_count',
'srid',
'bbox_x0',
'bbox_x1',
'bbox_y0',
'bbox_y1',
'category__gn_description',
'supplemental_information',
'thumbnail_url',
@@ -723,6 +739,15 @@ def format_objects(self, objects):
bundle)
# Add resource uri
formatted_obj['resource_uri'] = self.get_resource_uri(bundle)

# Probe Remote Services
formatted_obj['store_type'] = 'dataset'
formatted_obj['online'] = True
if hasattr(obj, 'storeType'):
formatted_obj['store_type'] = obj.storeType
if obj.storeType == 'remoteStore' and hasattr(obj, 'remote_service'):
formatted_obj['online'] = (obj.remote_service.probe == 200)

# put the object on the response stack
formatted_objects.append(formatted_obj)
return formatted_objects
@@ -879,6 +904,10 @@ def format_objects(self, objects):
formatted_obj['keywords'] = [k.name for k in obj.keywords.all()] if obj.keywords else []
formatted_obj['regions'] = [r.name for r in obj.regions.all()] if obj.regions else []

# Probe Remote Services
formatted_obj['store_type'] = 'map'
formatted_obj['online'] = True

# get map layers
map_layers = obj.layers
formatted_layers = []
@@ -941,6 +970,10 @@ def format_objects(self, objects):
formatted_obj['keywords'] = [k.name for k in obj.keywords.all()] if obj.keywords else []
formatted_obj['regions'] = [r.name for r in obj.regions.all()] if obj.regions else []

# Probe Remote Services
formatted_obj['store_type'] = 'dataset'
formatted_obj['online'] = True

formatted_objects.append(formatted_obj)
return formatted_objects

@@ -18,6 +18,8 @@
#
#########################################################################

import logging

from autocomplete_light.registry import register
from autocomplete_light.autocomplete.shortcuts import AutocompleteModelBase, AutocompleteModelTemplate

@@ -28,6 +30,8 @@

from models import ResourceBase, Region, HierarchicalKeyword, ThesaurusKeywordLabel

logger = logging.getLogger(__name__)


class ResourceBaseAutocomplete(AutocompleteModelTemplate):
choice_template = 'autocomplete_response.html'
@@ -85,7 +89,7 @@ def choices_for_request(self):
tname = thesaurus['name']
ac_name = 'thesaurus_' + tname

# print('Registering thesaurus autocomplete for {}: {}'.format(tname, ac_name))
logger.debug('Registering thesaurus autocomplete for {}: {}'.format(tname, ac_name))

register(
ThesaurusKeywordLabelAutocomplete,
@@ -130,6 +130,7 @@ def render(self, name, values, attrs=None):


class RegionsMultipleChoiceField(forms.MultipleChoiceField):

def validate(self, value):
"""
Validates that the input is a list or tuple.
@@ -0,0 +1,24 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('base', '0032_auto_20180329_1844'),
]

operations = [
migrations.AlterField(
model_name='region',
name='srid',
field=models.CharField(default=b'EPSG:4326', max_length=30),
),
migrations.AlterField(
model_name='resourcebase',
name='srid',
field=models.CharField(default=b'EPSG:4326', max_length=30),
),
]
@@ -202,7 +202,11 @@ class Region(MPTTModel):
decimal_places=15,
blank=True,
null=True)
srid = models.CharField(max_length=255, default='EPSG:4326')
srid = models.CharField(
max_length=30,
blank=False,
null=False,
default='EPSG:4326')

def __unicode__(self):
return self.name
@@ -691,7 +695,11 @@ class ResourceBase(PolymorphicModel, PermissionLevelMixin, ItemBase):
decimal_places=15,
blank=True,
null=True)
srid = models.CharField(max_length=255, default='EPSG:4326')
srid = models.CharField(
max_length=30,
blank=False,
null=False,
default='EPSG:4326')

# CSW specific fields
csw_typename = models.CharField(
@@ -868,15 +876,6 @@ def keyword_csv(self):
else:
return ''

def set_latlon_bounds(self, box):
"""
Set the four bounds in lat lon projection
"""
self.bbox_x0 = box[0]
self.bbox_x1 = box[1]
self.bbox_y0 = box[2]
self.bbox_y1 = box[3]

def set_bounds_from_center_and_zoom(self, center_x, center_y, zoom):
"""
Calculate zoom level and center coordinates in mercator.
@@ -918,7 +917,7 @@ def deg_len():
self.bbox_y0 = lat - distance_y_degrees
self.bbox_y1 = lat + distance_y_degrees

def set_bounds_from_bbox(self, bbox):
def set_bounds_from_bbox(self, bbox, srid):
"""
Calculate zoom level and center coordinates in mercator.
@@ -927,7 +926,19 @@ def set_bounds_from_bbox(self, bbox):
[xmin, xmax, ymin, ymax]
:type bbox: list
"""
self.set_latlon_bounds(bbox)
if not bbox or len(bbox) < 4:
raise ValidationError(
'Bounding Box cannot be empty %s for a given resource' %
self.name)
if not srid:
raise ValidationError(
'Projection cannot be empty %s for a given resource' %
self.name)
self.bbox_x0 = bbox[0]
self.bbox_x1 = bbox[1]
self.bbox_y0 = bbox[2]
self.bbox_y1 = bbox[3]
self.srid = srid

minx, maxx, miny, maxy = [float(c) for c in bbox]
x = (minx + maxx) / 2
@@ -1259,17 +1270,23 @@ def resourcebase_post_save(instance, *args, **kwargs):
link.delete()

try:
# set default License if no specified
if instance.license is None:
license = License.objects.filter(name="Not Specified")

if license and len(license) > 0:
instance.license = license[0]

ResourceBase.objects.filter(id=instance.id).update(
thumbnail_url=instance.get_thumbnail_url(),
detail_url=instance.get_absolute_url(),
csw_insert_date=datetime.datetime.now())
csw_insert_date=datetime.datetime.now(),
license=instance.license)
instance.refresh_from_db()
except BaseException:
pass

try:
instance.thumbnail_url = instance.get_thumbnail_url()
instance.detail_url = instance.get_absolute_url()
instance.csw_insert_date = datetime.datetime.now()
tb = traceback.format_exc()
if tb:
logger.debug(tb)
finally:
instance.set_missing_info()

@@ -1326,13 +1343,6 @@ def resourcebase_post_save(instance, *args, **kwargs):
if tb:
logger.debug(tb)

# set default License if no specified
if instance.license is None:
no_license = License.objects.filter(name="Not Specified")

if no_license and len(no_license) > 0:
instance.license = no_license[0]


def rating_post_save(instance, *args, **kwargs):
"""
@@ -20,7 +20,14 @@
<span class="item-category" ng-if="item.group"><a href="/groups/group/{{ item.group }}/activity/"><i class="fa fa-group" aria-hidden="true" style="margin-right: 8px;"></i>{{ item.group_name }}</a><br></span>
<span class="item-category" ng-if="item.has_time"><i class="fa fa-clock-o" aria-hidden="true" style="margin-right: 8px;"></i>Temporal Serie<br></span>
</p>
<h4><a href="{{ item.detail_url }}">{{ item.title }}</a></h4>
<h4>
<i ng-if="item.store_type == 'remoteStore'" title="Remote Service" class="fa fa-external-link fa-1" style="vertical-align: middle;padding-right: 10px;"></i>
<i ng-if="item.store_type == 'dataStore'" title="Vector Data" class="fa fa-pencil-square-o fa-1" style="vertical-align: middle;padding-right: 10px;"></i>
<i ng-if="item.store_type == 'coverageStore'" title="Raster Data" class="fa fa-picture-o fa-1" style="vertical-align: middle;padding-right: 10px;"></i>
<i ng-if="item.store_type == 'dataset'" title="File/Dataset" class="fa fa-newspaper-o fa-1" style="vertical-align: middle;padding-right: 10px;"></i>
<i ng-if="item.store_type == 'map'" title="Map" class="fa fa-map-o fa-1" style="vertical-align: middle;padding-right: 10px;"></i>
<a href="{{ item.detail_url }}">{{ item.title }}</a>
</h4>
</div>
<div class="col-xs-2">
<h4>
@@ -34,6 +41,12 @@ <h4>
</h4>
</div>
</div>
<em ng-if="item.store_type == 'remoteStore'">
{% endverbatim %}
<span ng-if="item.online == true"><i class="fa fa-power-off text-success"></i> {% trans "Service is" %} {% trans "online" %}</span>
<span ng-if="item.online == false"><i class="fa fa-power-off text-danger"></i> {% trans "Service is" %} {% trans "offline" %}</span>
{% verbatim %}
</em>
<div class="alert alert-warning" ng-if="item.is_approved == false">PENDING APPROVAL</div>
<div class="alert alert-danger" ng-if="item.is_approved == true && item.is_published == false">UNPUBLISHED</div>
<p class="abstract">{{ item.abstract | limitTo: 300 }}{{ item.abstract.length > 300 ? '...' : ''}}</p>
@@ -23,13 +23,16 @@

# Standard Modules
import os
import logging

# Django functionality
from django.conf import settings

# Geonode functionality
from geonode.documents.models import ResourceBase

logger = logging.getLogger('geonode.base.utils')


def delete_orphaned_thumbs():
"""
@@ -41,8 +44,8 @@ def delete_orphaned_thumbs():
model = filename.split('-')[0]
uuid = filename.replace(model, '').replace('-thumb.png', '')[1:]
if ResourceBase.objects.filter(uuid=uuid).count() == 0:
print 'Removing orphan thumb %s' % fn
logger.debug('Removing orphan thumb %s' % fn)
try:
os.remove(fn)
except OSError:
print 'Could not delete file %s' % fn
logger.debug('Could not delete file %s' % fn)
@@ -457,7 +457,7 @@
<gco:Boolean>0</gco:Boolean>
</gmd:includedWithDataset>
<gmd:MD_FeatureCatalogueDescription>
<gmd:featureCatalogueCitation xlink:href="{{ SITEURL }}{{ layer.get_absolute_url }}/feature_catalogue"/>
<gmd:featureCatalogueCitation uuidref="{{layer.uuid}}" xlink:href="{{ SITEURL }}{{ layer.get_absolute_url }}/feature_catalogue"/>
</gmd:MD_FeatureCatalogueDescription>
{% endif %}
</gmd:contentInfo>
@@ -23,7 +23,15 @@
class HookProxy(object):

def __getattr__(self, attr):
return getattr(settings.GEONODE_CLIENT_HOOKSET, attr)
if not isinstance(settings.GEONODE_CLIENT_HOOKSET, basestring):
return getattr(settings.GEONODE_CLIENT_HOOKSET, attr)
else:
import importlib
cls = settings.GEONODE_CLIENT_HOOKSET.split(".")
module_name, class_name = (".".join(cls[:-1]), cls[-1])
i = importlib.import_module(module_name)
hook = getattr(i, class_name)()
return getattr(hook, attr)


hookset = HookProxy()
@@ -147,38 +147,35 @@
var map = app.mapPanel.map;
var layer = app.map.layers.slice(-1)[0];
var bbox = layer.bbox;
var crs = layer.crs
var crs = layer.srs
if (bbox != undefined)
{
if (!Array.isArray(bbox) && Object.keys(layer.srs) in bbox) {
bbox = bbox[Object.keys(layer.srs)].bbox;
}
var extent = new OpenLayers.Bounds();
if(crs && crs.properties) {
extent.left = bbox[0];
extent.right = bbox[2];
extent.bottom = bbox[1];
extent.top = bbox[3];
if (crs.properties != map.projection) {
extent = extent.clone().transform(crs.properties, map.projection);
}
} else {
if (layer.capability.bbox &&
!Array.isArray(layer.capability.bbox) &&
map.projection in layer.capability.bbox) {
bbox = layer.capability.bbox[map.projection].bbox;
extent = OpenLayers.Bounds.fromArray(bbox);
} else {
if (crs != map.projection) {
extent = OpenLayers.Bounds.fromArray(bbox);
extent = extent.clone().transform(crs, map.projection);
} else {
extent = OpenLayers.Bounds.fromArray(bbox);
}
}
var zoomToData = function()
{
map.zoomToExtent(extent, false);
map.zoomToExtent(extent, true);
app.mapPanel.center = map.center;
app.mapPanel.zoom = map.zoom;
map.events.unregister('changebaselayer', null, zoomToData);
};
map.events.register('changebaselayer',null,zoomToData);
if(map.baseLayer){
map.zoomToExtent(extent, false);
map.zoomToExtent(extent, true);
}
}
},

0 comments on commit 0551910

Please sign in to comment.
You can’t perform that action at this time.