-
Notifications
You must be signed in to change notification settings - Fork 20
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
11 changed files
with
321 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
include LICENSE | ||
include README.md | ||
recursive-include wagtailinventory/templates *.html |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
from __future__ import absolute_import, unicode_literals | ||
|
||
from django import forms | ||
from django.db.models.fields import BLANK_CHOICE_DASH | ||
from django.forms import formset_factory | ||
from wagtail.wagtailcore.models import Page | ||
|
||
from wagtailinventory.models import PageBlock | ||
|
||
|
||
class PageBlockQueryForm(forms.Form): | ||
INCLUDES_BLOCK = 'includes' | ||
EXCLUDES_BLOCK = 'excludes' | ||
|
||
block = forms.ChoiceField( | ||
choices=(), | ||
required=False, | ||
label='Block type', | ||
widget=forms.Select(attrs={'style': 'width: 50%'}) | ||
) | ||
|
||
has = forms.ChoiceField( | ||
choices=((c, c) for c in (INCLUDES_BLOCK, EXCLUDES_BLOCK)), | ||
label=None, | ||
widget=forms.Select(attrs={'style': 'width: 100px'}) | ||
) | ||
|
||
def __init__(self, *args, **kwargs): | ||
super(PageBlockQueryForm, self).__init__(*args, **kwargs) | ||
block_choices = BLANK_CHOICE_DASH + [ | ||
(b, b) for b in | ||
PageBlock.objects.values_list('block', flat=True).distinct() | ||
] | ||
self.fields['block'].choices = block_choices | ||
|
||
|
||
class BasePageBlockQueryFormSet(forms.BaseFormSet): | ||
def get_query(self): | ||
qs = Page.objects.all() | ||
|
||
for form in self.forms: | ||
if not form.is_valid(): | ||
continue | ||
|
||
form_block = form.cleaned_data.get('block') | ||
|
||
if not form_block: | ||
continue | ||
|
||
condition = {'page_blocks__block': form_block} | ||
|
||
if form.cleaned_data['has'] == form.INCLUDES_BLOCK: | ||
qs = qs.filter(**condition) | ||
else: | ||
qs = qs.exclude(**condition) | ||
|
||
return qs | ||
|
||
|
||
PageBlockQueryFormSet = formset_factory( | ||
PageBlockQueryForm, | ||
formset=BasePageBlockQueryFormSet, | ||
extra=3, | ||
max_num=3 | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
from wagtail.wagtailcore.blocks import StreamValue, StructValue | ||
from wagtail.wagtailcore.fields import StreamField | ||
|
||
from wagtailinventory.models import PageBlock | ||
|
||
|
||
def get_block_name(block): | ||
return block.__module__ + '.' + block.__class__.__name__ | ||
|
||
|
||
def create_page_block(page, block, value): | ||
page_block, _ = PageBlock.objects.get_or_create( | ||
page=page, | ||
block=get_block_name(block) | ||
) | ||
|
||
page_blocks = [page_block] | ||
|
||
if isinstance(value, list): | ||
for subvalue in value: | ||
page_blocks.extend(create_page_block( | ||
page, | ||
block.child_block, | ||
subvalue | ||
)) | ||
elif isinstance(value, StructValue): | ||
for key, subvalue in value.bound_blocks.items(): | ||
page_blocks.extend(create_page_block( | ||
page, | ||
block.child_blocks[key], | ||
subvalue | ||
)) | ||
elif isinstance(value, StreamValue): | ||
for subvalue in value: | ||
page_blocks.extend(create_page_block( | ||
page, | ||
subvalue.block, | ||
subvalue.value | ||
)) | ||
|
||
return page_blocks | ||
|
||
|
||
def create_page_inventory(page): | ||
page_blocks = [] | ||
|
||
for field in page.specific._meta.fields: | ||
if not isinstance(field, StreamField): | ||
continue | ||
|
||
value = getattr(page.specific, field.name) | ||
|
||
for item in value: | ||
page_blocks.extend(create_page_block(page, item.block, item.value)) | ||
|
||
return page_blocks | ||
|
||
|
||
def get_page_inventory(page=None): | ||
inventory = PageBlock.objects.all() | ||
|
||
if page: | ||
inventory = inventory.filter(page=page) | ||
|
||
return inventory | ||
|
||
|
||
def delete_page_inventory(page=None): | ||
get_page_inventory(page).delete() | ||
|
||
|
||
def update_page_inventory(page): | ||
page_blocks = create_page_inventory(page) | ||
|
||
for page_block in get_page_inventory(page): | ||
if page_block not in page_blocks: | ||
page_block.delete() |
Empty file.
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
from __future__ import print_function | ||
|
||
from django.core.management import BaseCommand | ||
from wagtail.wagtailcore.models import Page | ||
|
||
from wagtailinventory.helpers import ( | ||
create_page_inventory, delete_page_inventory | ||
) | ||
|
||
|
||
class Command(BaseCommand): | ||
def handle(self, *args, **options): | ||
delete_page_inventory() | ||
|
||
count = Page.objects.count() | ||
for i, page in enumerate(Page.objects.all()): | ||
print(i + 1, '/', count, page) | ||
create_page_inventory(page) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
from __future__ import absolute_import, unicode_literals | ||
|
||
from django.db import models | ||
from django.utils.encoding import python_2_unicode_compatible | ||
from wagtail.wagtailcore.models import Page | ||
|
||
|
||
@python_2_unicode_compatible | ||
class PageBlock(models.Model): | ||
page = models.ForeignKey(Page, related_name='page_blocks') | ||
block = models.CharField(max_length=255, db_index=True) | ||
|
||
def __str__(self): | ||
return '<{}, {}>'.format(self.page, self.block) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
{% extends "wagtailadmin/base.html" %} | ||
{% load i18n %} | ||
{% load static %} | ||
{% load wagtailadmin_tags %} | ||
|
||
{% block titletag %}{% trans "Block Inventory" %}{% endblock %} | ||
|
||
{% block content %} | ||
{% trans "Block Inventory" as header_str %} | ||
{% include "wagtailadmin/shared/header.html" with title=header_str icon="placeholder" %} | ||
|
||
<form class="nice-padding" action="{% url 'wagtailinventory:search' %}"> | ||
{{ formset.management_form }} | ||
{% for form in formset %} | ||
<div> | ||
{{ form.has }} | ||
{{ form.block }} | ||
</div> | ||
{% endfor %} | ||
<input type="submit" value="Find matching pages" style="width: 240px; padding: 10px; margin: 10px 0" /> | ||
</form> | ||
|
||
<div id="search-results"> | ||
{% if pages %} | ||
<div class="nice-padding"> | ||
<h2> | ||
{% blocktrans count counter=pages.paginator.count %} | ||
There is one match | ||
{% plural %} | ||
There are {{ counter }} matches | ||
{% endblocktrans %} | ||
</h2> | ||
|
||
{% include "wagtailadmin/pages/listing/_list_explore.html" with show_parent=1 allow_navigation=0 %} | ||
{% paginate pages base_url=base_url classnames="navigate-pages" %} | ||
</div> | ||
{% else %} | ||
<div class="nice-padding"> | ||
<h2> | ||
{% blocktrans %}Sorry, there are no matching pages.{% endblocktrans %} | ||
</h2> | ||
</div> | ||
{% endif %} | ||
</div> | ||
{% endblock %} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
from __future__ import absolute_import, unicode_literals | ||
|
||
from django.test import TestCase | ||
|
||
from wagtail.wagtailcore.models import Page | ||
from wagtailinventory.models import PageBlock | ||
|
||
|
||
class TestPageBlock(TestCase): | ||
def test_page_str(self): | ||
page_block = PageBlock( | ||
page=Page(title='Title', slug='title'), | ||
block='path.to.block' | ||
) | ||
self.assertEqual(str(page_block), '<Title, path.to.block>') |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
from __future__ import absolute_import, unicode_literals | ||
|
||
from django.http import HttpResponseBadRequest | ||
from django.shortcuts import render | ||
from django.views.generic import View | ||
from wagtail.utils.pagination import paginate, replace_page_in_query | ||
from wagtail.wagtailcore.models import Page | ||
|
||
from wagtailinventory.forms import PageBlockQueryFormSet | ||
|
||
|
||
class SearchView(View): | ||
template_name = 'wagtailinventory/search.html' | ||
|
||
def get(self, request): | ||
if len(request.GET) > 1: | ||
formset = PageBlockQueryFormSet(request.GET) | ||
if not formset.is_valid(): | ||
return HttpResponseBadRequest('invalid query') | ||
|
||
pages = formset.get_query() | ||
else: | ||
formset = PageBlockQueryFormSet() | ||
pages = Page.objects.all() | ||
|
||
paginator, pages = paginate(request, pages.order_by('title')) | ||
|
||
for page in pages: | ||
page.can_choose = True | ||
|
||
return render(request, self.template_name, { | ||
'base_url': replace_page_in_query(request.GET.urlencode(), None), | ||
'formset': formset, | ||
'pages': pages, | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
from __future__ import absolute_import, unicode_literals | ||
|
||
from django.conf.urls import include, url | ||
from django.core.urlresolvers import reverse | ||
from wagtail.wagtailadmin.menu import MenuItem | ||
from wagtail.wagtailcore import hooks | ||
|
||
from wagtailinventory.helpers import ( | ||
create_page_inventory, delete_page_inventory, update_page_inventory | ||
) | ||
from wagtailinventory.views import SearchView | ||
|
||
|
||
@hooks.register('after_create_page') | ||
def do_after_page_create(request, page): | ||
create_page_inventory(page) | ||
|
||
|
||
@hooks.register('after_edit_page') | ||
def do_after_page_edit(request, page): | ||
update_page_inventory(page) | ||
|
||
|
||
@hooks.register('after_delete_page') | ||
def do_after_page_dete(request, page): | ||
delete_page_inventory(page) | ||
|
||
|
||
@hooks.register('register_admin_urls') | ||
def register_inventory_urls(): | ||
return [ | ||
url( | ||
r'^inventory/', | ||
include( | ||
[url(r'$', SearchView.as_view(), name='search')], | ||
namespace='wagtailinventory' | ||
) | ||
), | ||
] | ||
|
||
|
||
@hooks.register('register_settings_menu_item') | ||
def register_inventory_menu_item(): | ||
return MenuItem( | ||
'Block Inventory', | ||
reverse('wagtailinventory:search'), | ||
classnames='icon icon-placeholder', | ||
order=11000 | ||
) |