Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

publishing status for layers

- add to model to support layer status

- add in progress layers to favorites list

- adjust favorites layout

- minor cleanup

- UI for layers

- cleanup of map/layer pages
  • Loading branch information...
commit 08223b879040903499a9f59da7ac6a8e588fd8cd 1 parent 805391f
Ian Schneider ischneider authored
44 media/script/info.js
View
@@ -0,0 +1,44 @@
+$(function() {
+ $("#submit").click(function(ev) {
+ ev.preventDefault();
+ var form = $(this).closest('form');
+ form.find('.errorlist').fadeOut();
+ $.post(
+ form.attr('action'),
+ form.serialize(),
+ function() {
+ alert('Updated');
+ }
+ ).error(function(ev) {
+ $(ev.responseText).appendTo(form);
+ });
+ });
+ $("#publish_status").click(function(ev) {
+ ev.preventDefault();
+ $.post(
+ $(this).attr('href'),
+ function() {
+ $("#publish_info").fadeOut();
+ }
+ )
+ });
+ $("#topic-dropdown a").click(function(ev) {
+ ev.preventDefault();
+ $.post( topic_url, {
+ 'topics' : $(this).attr('href').substring(1)
+ },function() {
+ $(".topic-info.alert").fadeOut();
+ })
+ });
+ $("#publish-dropdown a").click(function(ev) {
+ var link = $(this);
+ ev.preventDefault();
+ $.post( publishing_url, {
+ 'status' : link.attr('href').substring(1)
+ },function() {
+ $("#current_publish_status").html(link.html());
+ link.closest('ul').find('.active').removeClass('active');
+ link.closest('li').addClass('active');
+ })
+ });
+});
1  media/theme/search.css
View
@@ -85,6 +85,7 @@
border: 2px solid #8E9184;
background: white;
padding: 5px;
+ margin-top: 10px;
}
#favorites ul {
padding: 0;
98 models.py
View
@@ -1,9 +1,13 @@
from itertools import chain
import random
+import operator
+import re
+from django.conf import settings
from django.db import models
from django.db.models import Count
from django.db.models import signals
+from django.db.models import Q
from django.contrib.contenttypes.models import ContentType
from django.contrib.contenttypes import generic
from django.core.urlresolvers import reverse
@@ -11,10 +15,22 @@
from django.contrib.auth.models import User
+from geonode.core.models import AUTHENTICATED_USERS
+from geonode.core.models import ANONYMOUS_USERS
from geonode.maps.models import Contact
from geonode.maps.models import Map
from geonode.maps.models import Layer
+'''Settings API - allow regular expressions to filter our layer name results'''
+if hasattr(settings,'SIMPLE_SEARCH_EXCLUSIONS'):
+ _exclude_patterns = settings.SIMPLE_SEARCH_EXCLUSIONS
+ _exclude_regex = [ re.compile(e) for e in _exclude_patterns ]
+_layer_name_filter = reduce(operator.or_,[ Q(name__regex=f) for f in _exclude_patterns])
+
+def filtered_layers():
+ return Layer.objects.exclude(_layer_name_filter)
+Layer.objects.filtered = filtered_layers
+
class SectionManager(models.Manager):
def sections_with_maps(self):
'''@todo this is broken - Get only those sections that have maps'''
@@ -70,10 +86,10 @@ def all_children(self):
return x
def get_maps(self):
- return self._children('maps', publish__status='Public')
+ return self._children('maps', publish__status=PUBLISHING_STATUS_PUBLIC)
def get_layers(self):
- return self._children('layers')
+ return self._children('layers', publish__status=PUBLISHING_STATUS_PUBLIC)
def save(self,*args,**kw):
slugtext = self.name.replace('&','and')
@@ -181,45 +197,69 @@ class Meta:
def __unicode__(self):
return "%s likes %s" % (self.user, self.content_object)
-_MAP_PUBLISHING_IN_PROGRESS = "In Progress"
-_MAP_PUBLISHING_PUBLIC = "Public"
-_MAP_PUBLISHING_CHOICES = [
- (_MAP_PUBLISHING_IN_PROGRESS,_MAP_PUBLISHING_IN_PROGRESS),
- (_MAP_PUBLISHING_PUBLIC,_MAP_PUBLISHING_PUBLIC),
+PUBLISHING_STATUS_PRIVATE = "Private"
+PUBLISHING_STATUS_LINK = "Link"
+PUBLISHING_STATUS_PUBLIC = "Public"
+PUBLISHING_STATUS_CHOICES = [
+ (PUBLISHING_STATUS_PRIVATE,PUBLISHING_STATUS_PRIVATE),
+ (PUBLISHING_STATUS_LINK,PUBLISHING_STATUS_LINK),
+ (PUBLISHING_STATUS_PUBLIC,PUBLISHING_STATUS_PUBLIC)
]
class PublishingStatusMananger(models.Manager):
- def get_public(self, user):
- return Map.objects.filter(owner=user, publish__status=_MAP_PUBLISHING_PUBLIC)
- def get_in_progress(self, user):
- return Map.objects.filter(owner=user, publish__status=_MAP_PUBLISHING_IN_PROGRESS)
- def set_status(self, mapobj, status):
- status = self.get_or_create(map_obj)
- status.status = status
- status.save()
- def set_public(self,map_obj):
- self.set_status(_MAP_PUBLISHING_PUBLIC)
- def set_in_progress(self,map_obj):
- self.set_status(_MAP_PUBLISHING_IN_PROGRESS)
+ def get_public(self, user, model):
+ return model.objects.filter(owner=user, publish__status=PUBLISHING_STATUS_PUBLIC)
+ def get_in_progress(self, user, model):
+ if model == Layer:
+ # don't show annotations
+ q = model.objects.filtered()
+ else:
+ q = model.objects.all()
+ q = q.filter(owner=user)
+ return q.exclude(publish__status=PUBLISHING_STATUS_PUBLIC)
+ def get_or_create_for(self, obj):
+ if isinstance(obj, Map):
+ status, _ = self.get_or_create(map=obj)
+ else:
+ status, _ = self.get_or_create(layer=obj)
+ return status
+ def set_status(self, obj, status):
+ stat = self.get_or_create_for(obj)
+ stat.status = status
+ stat.save()
class PublishingStatus(models.Model):
+ '''This is a denormalized model - could have gone with a content-type
+ but it seemed to make the queries much more complex than needed.
+
+ Each entry should either have a map or a layer.
+ '''
+
objects = PublishingStatusMananger()
- map = models.OneToOneField(Map,related_name='publish')
- status = models.CharField(max_length=16,choices=_MAP_PUBLISHING_CHOICES,default=_MAP_PUBLISHING_IN_PROGRESS)
+ map = models.OneToOneField(Map,related_name='publish',null=True)
+ layer = models.OneToOneField(Layer,related_name='publish',null=True)
+ status = models.CharField(max_length=8,choices=PUBLISHING_STATUS_CHOICES,default=PUBLISHING_STATUS_PRIVATE)
- def get_toggle_value(self):
- if self.status == _MAP_PUBLISHING_IN_PROGRESS:
- return _MAP_PUBLISHING_PUBLIC
- return _MAP_PUBLISHING_IN_PROGRESS
+ def save(self,*args,**kw):
+ obj = self.layer or self.map
+ level = obj.LEVEL_READ
+ if self.status == PUBLISHING_STATUS_PRIVATE:
+ level = obj.LEVEL_NONE
+ obj.set_gen_level(ANONYMOUS_USERS, level)
+ obj.set_gen_level(AUTHENTICATED_USERS, level)
+ obj.set_user_level(obj.owner, obj.LEVEL_ADMIN)
+ models.Model.save(self,*args)
+
def create_profile(instance, sender, **kw):
if kw['created']:
ContactDetail.objects.create(user = instance)
-
+
def create_publishing_status(instance, sender, **kw):
if kw['created']:
- PublishingStatus.objects.create(map = instance)
-
+ PublishingStatus.objects.get_or_create_for(instance)
+
signals.post_save.connect(create_profile, sender=User)
-signals.post_save.connect(create_publishing_status, sender=Map)
+signals.post_save.connect(create_publishing_status, sender=Map)
+signals.post_save.connect(create_publishing_status, sender=Layer)
16 templates/maps/_widget_publish_status.html
View
@@ -0,0 +1,16 @@
+<p>Publishing Status : <span style="font-weight: bold" id="current_publish_status">{{ current_status }}</span></p>
+<div class="btn-group" id="publish-dropdown">
+ <button class="btn dropdown-toggle" data-toggle="dropdown">
+ Change Status<span class="caret"></span>
+ </button>
+ <ul class="dropdown-menu">
+ {% for s in publish_options %}
+ <li class="{% if current_status == s.value %}active{% endif %}"><a href="#{{s.key}}">{{s.value}}</a></li>
+ {% endfor %}
+ </ul>
+</div>
+<script type="text/javascript">
+{% autoescape off %}
+var publishing_url = "{% url publish_status publish_object_type publish_object.pk %}";
+{% endautoescape %}
+</script>
11 templates/maps/_widget_topic_selection.html
View
@@ -30,15 +30,6 @@
</div>
<script type="text/javascript">
{% autoescape off %}
-$(function(objectid) {
- $("#topic-dropdown a").click(function(ev) {
- ev.preventDefault();
- $.post( "{% url topics_api topic_object_type topic_object.pk %}", {
- 'topics' : $(this).attr('href').substring(1)
- },function() {
- $(".topic-info.alert").fadeOut();
- })
- });
-});
+var topic_url = "{% url topics_api topic_object_type topic_object.pk %}";
{% endautoescape %}
</script>
20 templates/maps/layer.html
View
@@ -11,6 +11,7 @@
{% include "geonode/app_header.html" %}
{% include "geonode/geo_header.html" %}
<script type="text/javascript" src="{{ STATIC_URL}}script/favorites.js"></script>
+<script type="text/javascript" src="{{ STATIC_URL}}script/info.js"></script>
<script type="text/javascript">
{% autoescape off %}
var styleEditor, modified = false;
@@ -167,24 +168,13 @@ <h2 class="icn-storylayers">{{ layer.title }}</h2>
</div>
{% csrf_token %}
</form>
+ <hr/>
{% topic_selection layer %}
- <script type="text/javascript">
- $(function() {
- $("#submit").click(function(ev) {
- ev.preventDefault();
- var form = $(this).closest('form');
- $.post(
- form.attr('action'),
- form.serialize(),
- function() {
- alert('updated');
- }
- );
- });
- });
- </script>
+ <hr/>
<p>Generate a thumbnail for this map</p>
<a id="set_thumbnail" class="btn" href="#thumbnail">{% trans "Set thumbnail" %}</a>
+ <hr/>
+ {% publish_status layer %}
{% else %}
<label>Title:</label>
<p>{{ layer.title }}</p>
41 templates/maps/mapinfo.html
View
@@ -12,6 +12,7 @@
{% include "geonode/app_header.html" %}
{% include "geonode/geo_header.html" %}
<script type="text/javascript" src="{{ STATIC_URL}}script/favorites.js"></script>
+<script type="text/javascript" src="{{ STATIC_URL}}script/info.js"></script>
{{ block.super }}
<script type="text/javascript">
var app;
@@ -99,43 +100,15 @@ <h2 class="icn-storylayers">{{ map.title }}</h2>
<div>
<button class="btn" id="submit">Update Information</button>
</div>
- {% topic_selection map %}
{% csrf_token %}
+ </form>
+ <hr/>
+ {% topic_selection map %}
+ <hr/>
<p>Generate a thumbnail for this map</p>
<a id="set_thumbnail" class="btn" href="#thumbnail">{% trans "Set thumbnail" %}</a>
- </form>
- <script type="text/javascript">
- $(function() {
- $("#submit").click(function(ev) {
- ev.preventDefault();
- var form = $(this).closest('form');
- form.find('.errorlist').fadeOut();
- $.post(
- form.attr('action'),
- form.serialize(),
- function() {
- alert('Updated');
- }
- ).error(function(ev) {
- $(ev.responseText).appendTo(form);
- });
- });
- $("#publish_status").click(function(ev) {
- ev.preventDefault();
- $.post(
- $(this).attr('href'),
- function() {
- $("#publish_info").fadeOut();
- }
- )
- });
- });
- </script>
- <div id="publish_info">
- <p>Publish this map (or not):</p>
- <p>The current status is <b>{{map.publish.status}}</b></p>
- <a id="publish_status" href="{% url publish_status map.id map.publish.get_toggle_value %}" class="btn">Make {{map.publish.get_toggle_value}}</a>
- </div>
+ <hr/>
+ {% publish_status map %}
{% else %}
<label>Title:</label>
<p>{{ map.title }}</p>
18 templates/mapstory/_widget_favorites.html
View
@@ -1,8 +1,9 @@
-{% if not favorites and not in_progress %}
+{% if not favorites and not in_progress_maps or not in_progress_layers %}
You have not selected any favorites.
{% endif %}
{% if favorites %}
+<h4>Favorites</h4>
<ul>
{% for f in favorites %}
<li>
@@ -13,10 +14,21 @@
</ul>
{% endif %}
-{% if in_progress %}
+{% if in_progress_maps %}
<h4>MapStories In Progress</h4>
<ul>
-{% for f in in_progress %}
+{% for f in in_progress_maps %}
+ <li>
+ <a href="{{ f.get_absolute_url }}">{{ f.title }}</a>
+ </li>
+{% endfor %}
+</ul>
+{% endif %}
+
+{% if in_progress_layers %}
+<h4>StoryLayers In Progress</h4>
+<ul>
+{% for f in in_progress_layers %}
<li>
<a href="{{ f.get_absolute_url }}">{{ f.title }}</a>
</li>
1  templates/simplesearch/search.html
View
@@ -51,7 +51,6 @@ <h2 style="margin-top: 10px">{% trans "Search MapStory" %}</h2>
<input id="searchField" name="search">
</form>
{% if user.is_authenticated %}
- <h5 style="color:#F46817">Favorites</h5>
<div id="favorites">
{% favorites %}
</div>
44 templatetags/mapstory_tags.py
View
@@ -10,6 +10,9 @@
from mapstory.models import Section
from mapstory.models import Favorite
from mapstory.models import PublishingStatus
+from mapstory.models import PUBLISHING_STATUS_PRIVATE
+from mapstory.models import PUBLISHING_STATUS_LINK
+from mapstory.models import PUBLISHING_STATUS_PUBLIC
import re
@@ -85,6 +88,36 @@ def render(self, context):
return loader.render_to_string(template_name,{'map':obj})
@register.tag
+def publish_status(parse, token):
+ try:
+ tokens = token.split_contents()
+ tag_name = tokens.pop(0)
+ obj_name = tokens.pop(0)
+ except ValueError:
+ raise template.TemplateSyntaxError, "%r tag requires a single argument" % token.contents.split()[0]
+ return PublishStatusNode(obj_name)
+
+class PublishStatusNode(template.Node):
+ def __init__(self, obj_name):
+ self.obj_name = obj_name
+ options = [
+ (PUBLISHING_STATUS_PRIVATE,"Only visible to me"),
+ (PUBLISHING_STATUS_LINK,"Anyone with a link can view"),
+ (PUBLISHING_STATUS_PUBLIC,"Anyone can search for and view"),
+ ]
+ self.options = [ dict(key=o[0],value=o[1]) for o in options ]
+ def render(self, context):
+ obj = context[self.obj_name]
+ template_name = "maps/_widget_publish_status.html"
+ current_status = [ o['value'] for o in self.options if o['key'] == obj.publish.status ][0]
+ return loader.render_to_string(template_name,{
+ 'publish_object': obj,
+ 'publish_options' : self.options,
+ 'current_status' : current_status,
+ 'publish_object_type': isinstance(obj, Map) and 'map' or 'layer'
+ })
+
+@register.tag
def topic_selection(parse, token):
try:
tokens = token.split_contents()
@@ -174,9 +207,12 @@ class FavoritesNode(template.Node):
def render(self, context):
template_name = "mapstory/_widget_favorites.html"
user = context['user']
+ maps = PublishingStatus.objects.get_in_progress(user,Map)
+ layers = PublishingStatus.objects.get_in_progress(user,Layer)
ctx = {
"favorites" : Favorite.objects.favorites_for_user(user),
- "in_progress" : Map.objects.filter(owner=user, publish__status='In Progress')
+ "in_progress_maps" : maps,
+ "in_progress_layers" : layers
}
return loader.render_to_string(template_name,ctx)
@@ -220,7 +256,7 @@ def render(self, context):
user = context['user']
template_name = 'mapstory/_widget_add_to_map.html'
return loader.render_to_string(template_name,{
- 'maps' : PublishingStatus.objects.get_in_progress(user), # user.map_set.all()
+ 'maps' : PublishingStatus.objects.get_in_progress(user,Map), # user.map_set.all()
'layer' : layer
})
@@ -244,10 +280,10 @@ def render(self, context):
else:
user = obj.owner
template_name = "maps/_widget_by_storyteller.html"
- layers = user.layer_set.all()
+ layers = PublishingStatus.objects.get_public(user, Layer)
for e in settings.LAYER_EXCLUSIONS:
layers = layers.exclude(name__regex=e)
- maps = set(PublishingStatus.objects.get_public(user))
+ maps = set(PublishingStatus.objects.get_public(user, Map))
#@todo could make query more efficient/explicit to exclude map
if obj in maps:
maps.remove(obj)
2  urls.py
View
@@ -50,7 +50,7 @@
url(r'^favorite/map/(?P<id>\d+)$','favorite',{'layer_or_map':'map'}, name='add_favorite_map'),
url(r'^favorite/layer/(?P<id>\d+)$','favorite',{'layer_or_map':'layer'}, name='add_favorite_layer'),
url(r'^favorite/(?P<id>\d+)/delete$','delete_favorite',name='delete_favorite'),
- url(r'^mapstory/public/(?P<id>\d+)/(?P<status>[ \w]+)','publish_status',name='publish_status'),
+ url(r'^mapstory/publish/(?P<layer_or_map>\w+)/(?P<layer_or_map_id>\d+)$','publish_status',name='publish_status'),
url(r'^mapstory/add-to-map/(?P<id>\d+)/(?P<typename>[:\w]+)','add_to_map',name='add_to_map'),
url(r'^search/favoriteslinks$','favoriteslinks',name='favoriteslinks'),
url(r'^search/favoriteslist$','favoriteslist',name='favoriteslist'),
20 views.py
View
@@ -34,7 +34,8 @@ def index(req):
# 1) don't specify publish and one will randomly be chosen
# 2) specify one or more publish links and one will be chosen
- users = User.objects.exclude(username__in=settings.USERS_TO_EXCLUDE_IN_LISTINGS)
+ #users = User.objects.exclude(username__in=settings.USERS_TO_EXCLUDE_IN_LISTINGS)
+ users = []
return render_to_response('index.html', RequestContext(req,{
"video" : VideoLink.objects.front_page_video(),
@@ -100,7 +101,7 @@ def favoriteslinks(req):
layer_or_map, id = ident.split('-')
if layer_or_map == 'map':
obj = get_object_or_404(Map, pk = id)
- maps = PublishingStatus.objects.get_in_progress(req.user)
+ maps = PublishingStatus.objects.get_in_progress(req.user,Map)
elif layer_or_map == 'layer':
obj = get_object_or_404(Layer, pk = id)
maps = None
@@ -169,15 +170,16 @@ def set_section(req):
return HttpResponse('OK', status=200)
@login_required
-def publish_status(req,id,status):
+def publish_status(req, layer_or_map, layer_or_map_id):
if req.method != 'POST':
return HttpResponse('POST required',status=400)
- mapobj = get_object_or_404(Map, id=id)
- if mapobj.owner != req.user and not req.user.has_perm('mapstory.change_section', mapobj):
+ if layer_or_map == 'map':
+ obj = get_object_or_404(Map, pk = layer_or_map_id)
+ else:
+ obj = get_object_or_404(Layer, pk = layer_or_map_id)
+ if obj.owner != req.user and not req.user.has_perm('mapstory.change_publishingstatus', obj):
return HttpResponse('Not sufficient permissions',status=401)
- pubobj, _ = PublishingStatus.objects.get_or_create(map = mapobj)
- pubobj.status = status
- pubobj.save()
+ PublishingStatus.objects.set_status(obj, req.POST['status'])
return HttpResponse('OK', status=200)
@login_required
@@ -185,7 +187,7 @@ def add_to_map(req,id,typename):
if req.method != 'POST':
return HttpResponse('POST required',status=400)
mapobj = get_object_or_404(Map, id=id)
- if mapobj.owner != req.user and not req.user.has_perm('mapstory.change_section', mapobj):
+ if mapobj.owner != req.user and not req.user.has_perm('maps.change_map', mapobj):
return HttpResponse('Not sufficient permissions',status=401)
layer = get_object_or_404(Layer, typename=typename)
existing = MapLayer.objects.filter(map = mapobj)
Please sign in to comment.
Something went wrong with that request. Please try again.