Skip to content
This repository has been archived by the owner on Aug 26, 2022. It is now read-only.

Commit

Permalink
fix bug 907236, bug 907238: Content zone models & logic, initial per-…
Browse files Browse the repository at this point in the history
…zone styles
  • Loading branch information
lmorchard committed Aug 22, 2013
1 parent 8987063 commit 16563ae
Show file tree
Hide file tree
Showing 12 changed files with 683 additions and 5 deletions.
7 changes: 6 additions & 1 deletion apps/wiki/admin.py
Expand Up @@ -7,7 +7,7 @@

from sumo.urlresolvers import reverse, split_path

from wiki.models import (Document, DocumentTag, Revision,
from wiki.models import (Document, DocumentZone, DocumentTag, Revision,
EditorToolbar,
Attachment, AttachmentRevision)

Expand Down Expand Up @@ -271,7 +271,12 @@ class AttachmentRevisionAdmin(admin.ModelAdmin):
search_fields = ('title', 'description')


class DocumentZoneAdmin(admin.ModelAdmin):
raw_id_fields = ('document',)


admin.site.register(Document, DocumentAdmin)
admin.site.register(DocumentZone, DocumentZoneAdmin)
admin.site.register(DocumentTag, admin.ModelAdmin)
admin.site.register(Revision, RevisionAdmin)
admin.site.register(EditorToolbar, admin.ModelAdmin)
Expand Down
20 changes: 20 additions & 0 deletions apps/wiki/helpers.py
Expand Up @@ -202,3 +202,23 @@ def colorize_diff(diff):
def wiki_bleach(val):
from wiki.models import Document
return jinja2.Markup(Document.objects.clean_content(val))


@register.function
def document_zone_management_links(user, document):
links = {'add': None, 'change': None}
zone = document.find_zone()

# Enable "add" link if there is no zone for this document, or if there's a
# zone but the document is not itself the root (ie. to add sub-zones).
if ((not zone or zone.document != document) and
user.has_perm('wiki.add_documentzone')):
links['add'] = '%s?document=%s' % (
reverse('admin:wiki_documentzone_add'), document.id)

# Enable "change" link if there's a zone, and the user has permission.
if zone and user.has_perm('wiki.change_documentzone'):
links['change'] = reverse('admin:wiki_documentzone_change',
args=(zone.id,))

return links
233 changes: 233 additions & 0 deletions apps/wiki/migrations/0029_auto__add_documentzone.py

Large diffs are not rendered by default.

228 changes: 228 additions & 0 deletions apps/wiki/migrations/0030_auto__add_unique_documentzone_document.py

Large diffs are not rendered by default.

24 changes: 23 additions & 1 deletion apps/wiki/models.py
Expand Up @@ -1482,14 +1482,29 @@ def filter_permissions(self, user, permissions):
# No-op, for now.
return permissions

def get_permission_parents(self):
def get_topic_parents(self):
"""Build a list of parent topics from self to root"""
curr, parents = self, []
while curr.parent_topic:
curr = curr.parent_topic
parents.append(curr)
return parents

def get_permission_parents(self):
return self.get_topic_parents()

def find_zone(self):
try:
return DocumentZone.objects.get(document=self)
except DocumentZone.DoesNotExist:
pass
for p in self.get_topic_parents():
try:
return DocumentZone.objects.get(document=p)
except DocumentZone.DoesNotExist:
pass
return None

def allows_revision_by(self, user):
"""Return whether `user` is allowed to create new revisions of me.
Expand Down Expand Up @@ -1705,6 +1720,13 @@ def bleach_matches(matches):
return u'...'.join(stripped_matches)


class DocumentZone(models.Model):
"""Model object declaring a content zone root at a given Document, provides
attributes inherited by the topic hierarchy beneath it."""
document = models.ForeignKey(Document, related_name='zones', unique=True)
styles = models.TextField(null=True, blank=True)


class ReviewTag(TagBase):
"""A tag indicating review status, mainly for revisions"""
class Meta:
Expand Down
8 changes: 8 additions & 0 deletions apps/wiki/templates/wiki/document.html
Expand Up @@ -16,6 +16,14 @@
{% set help_link = url('wiki.translate', document_path=document.parent.full_path, locale=document.parent.locale)|urlparams(tolocale=request.locale) %}
{% endif %}

{% block site_css %}
{{ super() }}
{% set zone = document.find_zone() %}
{% if zone %}
<link rel="stylesheet" type="text/css" href="{{ url('wiki.styles', zone.document.full_path) }}" />
{% endif %}
{% endblock %}

{% block extrahead %}
<link rel="alternate" type="application/json" href="{{ url('wiki.json_slug', document.full_path) }}" />
<link rel="canonical" href="{{ canonical }}" />
Expand Down
8 changes: 8 additions & 0 deletions apps/wiki/templates/wiki/includes/document_content.html
Expand Up @@ -40,6 +40,14 @@
{% elif policy_links['add'] %}
<li><a target="_blank" href="{{ policy_links['add'] }}">{{ _('Add access policy') }}</a></li>
{% endif %}

{% set zone_links = document_zone_management_links(request.user, document) %}
{% if zone_links['change'] %}
<li><a target="_blank" href="{{ zone_links['change'] }}">{{ _('Manage content zone') }}</a></li>
{% endif %}
{% if zone_links['add'] %}
<li><a target="_blank" href="{{ zone_links['add'] }}">{{ _('Convert to content zone') }}</a></li>
{% endif %}
</ul>
</li>
{% if document.is_localizable or document.parent %}
Expand Down
54 changes: 52 additions & 2 deletions apps/wiki/tests/test_helpers.py
@@ -1,7 +1,13 @@
from nose.tools import eq_
import logging

from nose.tools import eq_, ok_

from django.contrib.auth.models import User

from wiki.tests import TestCaseBase, revision
from wiki.helpers import revisions_unified_diff
from wiki.helpers import (revisions_unified_diff,
document_zone_management_links)
from wiki.models import DocumentZone, Document, Revision


class RevisionsUnifiedDiffTests(TestCaseBase):
Expand All @@ -14,3 +20,47 @@ def test_from_revision_none(self):
except AttributeError:
self.fail("Should not throw AttributeError")
eq_("Diff is unavailable.", diff)

class DocumentZoneTests(TestCaseBase):
"""Tests for DocumentZone helpers"""
fixtures = ['test_users.json']

def setUp(self):
super(DocumentZoneTests, self).setUp()

root_rev = revision(title='ZoneRoot', slug='ZoneRoot',
content='This is the Zone Root',
is_approved=True, save=True)
self.root_doc = root_rev.document

self.root_zone = DocumentZone(document=self.root_doc)
self.root_zone.save()

sub_rev = revision(title='SubPage', slug='SubPage',
content='This is a subpage',
is_approved=True, save=True)
self.sub_doc = sub_rev.document
self.sub_doc.parent_topic = self.root_doc
self.sub_doc.save()

other_rev = revision(title='otherPage', slug='otherPage',
content='This is an other page',
is_approved=True, save=True)
self.other_doc = other_rev.document
self.other_doc.save()

def test_document_zone_links(self):
admin = User.objects.filter(is_superuser=True)[0]
random = User.objects.filter(is_superuser=False)[0]
cases = [
(admin, self.root_doc, False, True),
(random, self.root_doc, False, False),
(admin, self.sub_doc, True, True),
(random, self.sub_doc, False, False),
(admin, self.other_doc, True, False),
(random, self.other_doc, False, False),
]
for (user, doc, add, change) in cases:
result_links = document_zone_management_links(user, doc)
eq_(add, (result_links['add'] is not None))
eq_(change, (result_links['change'] is not None))
41 changes: 40 additions & 1 deletion apps/wiki/tests/test_models.py
Expand Up @@ -27,7 +27,7 @@

from wiki.cron import calculate_related_documents
from wiki.models import (FirefoxVersion, OperatingSystem, Document, Revision,
Attachment,
Attachment, DocumentZone,
REDIRECT_CONTENT, REDIRECT_SLUG, REDIRECT_TITLE,
MAJOR_SIGNIFICANCE, CATEGORIES,
get_current_or_latest_revision,
Expand Down Expand Up @@ -1629,3 +1629,42 @@ def test_preserve_tags(self):
eq_(tags, new_rev.tags)
eq_(['technical'],
[str(tag) for tag in new_rev.review_tags.all()])


class DocumentZoneTests(TestCase):
"""Tests for content zones in topic hierarchies"""
fixtures = ['test_users.json']

def test_find_root(self):
"""Ensure sub pages can find the content zone root"""
root_rev = revision(title='ZoneRoot', slug='ZoneRoot',
content='This is the Zone Root',
is_approved=True, save=True)
root_doc = root_rev.document

sub_rev = revision(title='SubPage', slug='SubPage',
content='This is a subpage',
is_approved=True, save=True)
sub_doc = sub_rev.document
sub_doc.parent_topic = root_doc
sub_doc.save()

sub_sub_rev = revision(title='SubSubPage', slug='SubSubPage',
content='This is a subsubpage',
is_approved=True, save=True)
sub_sub_doc = sub_sub_rev.document
sub_sub_doc.parent_topic = sub_doc
sub_sub_doc.save()

other_rev = revision(title='otherPage', slug='otherPage',
content='This is an otherpage',
is_approved=True, save=True)
other_doc = other_rev.document

root_zone = DocumentZone(document=root_doc)
root_zone.save()

eq_(root_zone, root_doc.find_zone())
eq_(root_zone, sub_doc.find_zone())
eq_(root_zone, sub_sub_doc.find_zone())
eq_(None, other_doc.find_zone())
51 changes: 51 additions & 0 deletions apps/wiki/tests/test_views.py
Expand Up @@ -48,6 +48,7 @@
from wiki.content import get_seo_description
from wiki.events import EditDocumentEvent
from wiki.models import (VersionMetadata, Document, Revision, Attachment,
DocumentZone,
AttachmentRevision, DocumentAttachment, TOC_DEPTH_H4)
from wiki.tests import (doc_rev, document, new_document_data, revision,
normalize_html, create_template_test_users)
Expand Down Expand Up @@ -4055,3 +4056,53 @@ def test_mid_move(self):
moved_grandchild = Document.objects.get(slug=moved_grandchild_slug)
ok_('REDIRECT' in redirected_grandchild.html)
ok_(moved_grandchild_slug in redirected_grandchild.html)


class DocumentZoneTests(TestCaseBase):
fixtures = ['test_users.json']

def setUp(self):
super(DocumentZoneTests, self).setUp()

root_rev = revision(title='ZoneRoot', slug='ZoneRoot',
content='This is the Zone Root',
is_approved=True, save=True)
self.root_doc = root_rev.document

sub_rev = revision(title='SubPage', slug='SubPage',
content='This is a subpage',
is_approved=True, save=True)
self.sub_doc = sub_rev.document
self.sub_doc.parent_topic = self.root_doc
self.sub_doc.save()

self.root_zone = DocumentZone(document=self.root_doc)
self.root_zone.styles = """
article { color: blue; }
"""
self.root_zone.save()

def test_zone_styles(self):
"""Ensure CSS styles for a zone can be fetched"""
url = reverse('wiki.styles', args=(self.root_doc.slug,),
locale=settings.WIKI_DEFAULT_LANGUAGE)
response = self.client.get(url, follow=True)
eq_(self.root_zone.styles, response.content)

url = reverse('wiki.styles', args=(self.sub_doc.slug,),
locale=settings.WIKI_DEFAULT_LANGUAGE)
response = self.client.get(url, follow=True)
eq_(404, response.status_code)

def test_zone_styles_link(self):
"""Ensure link to zone style appears in child document views"""
url = reverse('wiki.document', args=(self.sub_doc.slug,),
locale=settings.WIKI_DEFAULT_LANGUAGE)
response = self.client.get(url, follow=True)

styles_url = reverse('wiki.styles', args=(self.root_doc.slug,),
locale=settings.WIKI_DEFAULT_LANGUAGE)
expected = ('<link rel="stylesheet" type="text/css" href="%s"' %
styles_url)

ok_(expected in response.content)
1 change: 1 addition & 0 deletions apps/wiki/urls.py
Expand Up @@ -22,6 +22,7 @@
url(r'^\$translate$', 'translate', name='wiki.translate'),
url(r'^\$locales$', 'select_locale', name='wiki.select_locale'),
url(r'^\$json$', 'json_view', name='wiki.json_slug'),
url(r'^\$styles$', 'styles_view', name='wiki.styles'),
url(r'^\$toc$', 'toc_view', name='wiki.toc'),
url(r'^\$move$', 'move', name='wiki.move'),
url(r'^\$quick-review$', 'quick_review', name='wiki.quick_review'),
Expand Down
13 changes: 13 additions & 0 deletions apps/wiki/views.py
Expand Up @@ -63,6 +63,7 @@
RevisionValidationForm, AttachmentRevisionForm,
TreeMoveForm)
from wiki.models import (Document, Revision, HelpfulVote, EditorToolbar,
DocumentZone,
DocumentTag, ReviewTag, Attachment,
DocumentRenderedContentNotAvailable,
CATEGORIES,
Expand Down Expand Up @@ -1850,6 +1851,18 @@ def json_view(request, document_slug=None, document_locale=None):
return HttpResponse(data, mimetype='application/json')


@require_GET
@allow_CORS_GET
@process_document_path
@prevent_indexing
def styles_view(request, document_slug=None, document_locale=None):
"""Return some basic document info in a JSON blob."""
kwargs = {'slug': document_slug, 'locale': document_locale}
document = get_object_or_404(Document, **kwargs)
zone = get_object_or_404(DocumentZone, document=document)
return HttpResponse(zone.styles, mimetype='text/css')


@require_GET
@allow_CORS_GET
@process_document_path
Expand Down

0 comments on commit 16563ae

Please sign in to comment.