Finished conversion of Mayan to the new document grouping app and paradigm

This commit is contained in:
Roberto Rosario
2011-05-12 04:03:05 -04:00
parent 06bf7e8c50
commit bc252d4ae4
24 changed files with 461 additions and 321 deletions

View File

@@ -11,6 +11,10 @@ from tags.widgets import get_tags_inline_widget_simple
from documents.models import Document, DocumentPage, DocumentPageTransformation from documents.models import Document, DocumentPage, DocumentPageTransformation
from documents.staging import StagingFile from documents.staging import StagingFile
from documents.conf.settings import ENABLE_SINGLE_DOCUMENT_UPLOAD from documents.conf.settings import ENABLE_SINGLE_DOCUMENT_UPLOAD
from documents.literals import PERMISSION_DOCUMENT_CREATE, \
PERMISSION_DOCUMENT_PROPERTIES_EDIT, PERMISSION_DOCUMENT_VIEW, \
PERMISSION_DOCUMENT_DELETE, PERMISSION_DOCUMENT_DOWNLOAD, \
PERMISSION_DOCUMENT_TRANSFORM, PERMISSION_DOCUMENT_TOOLS
PERMISSION_DOCUMENT_CREATE = 'document_create' PERMISSION_DOCUMENT_CREATE = 'document_create'
PERMISSION_DOCUMENT_PROPERTIES_EDIT = 'document_properties_edit' PERMISSION_DOCUMENT_PROPERTIES_EDIT = 'document_properties_edit'
@@ -72,17 +76,13 @@ document_page_rotate_left = {'text': _(u'rotate left'), 'class': 'no-parent-hist
document_missing_list = {'text': _(u'Find missing document files'), 'view': 'document_missing_list', 'famfam': 'folder_page', 'permissions': {'namespace': 'documents', 'permissions': [PERMISSION_DOCUMENT_VIEW]}} document_missing_list = {'text': _(u'Find missing document files'), 'view': 'document_missing_list', 'famfam': 'folder_page', 'permissions': {'namespace': 'documents', 'permissions': [PERMISSION_DOCUMENT_VIEW]}}
metadata_group_link = {'text': _(u'group actions'), 'view': 'metadatagroup_view', 'famfam': 'page_go', 'permissions': {'namespace': 'documents', 'permissions': [PERMISSION_DOCUMENT_VIEW]}}
metadata_group_back_to_document = {'text': _(u'return to document'), 'view': 'document_view_simple', 'args': 'ref_object.id', 'famfam': 'page', 'permissions': {'namespace': 'documents', 'permissions': [PERMISSION_DOCUMENT_VIEW]}}
metadata_group_create_sibling = {'text': _(u'upload new document using same metadata'), 'view': 'document_create_sibling', 'args': 'ref_object.id', 'famfam': 'page_copy', 'permissions': {'namespace': 'documents', 'permissions': [PERMISSION_DOCUMENT_CREATE]}}
staging_file_preview = {'text': _(u'preview'), 'class': 'fancybox-noscaling', 'view': 'staging_file_preview', 'args': 'object.id', 'famfam': 'drive_magnify'} staging_file_preview = {'text': _(u'preview'), 'class': 'fancybox-noscaling', 'view': 'staging_file_preview', 'args': 'object.id', 'famfam': 'drive_magnify'}
staging_file_delete = {'text': _(u'delete'), 'view': 'staging_file_delete', 'args': 'object.id', 'famfam': 'drive_delete'} staging_file_delete = {'text': _(u'delete'), 'view': 'staging_file_delete', 'args': 'object.id', 'famfam': 'drive_delete'}
register_links(Document, [document_view_simple, document_view_advanced, document_edit, document_print, document_delete, document_download, document_find_duplicates, document_clear_transformations]) register_links(Document, [document_view_simple, document_view_advanced, document_edit, document_print, document_delete, document_download, document_find_duplicates, document_clear_transformations])
register_links(Document, [document_create_sibling], menu_name='sidebar') register_links(Document, [document_create_sibling], menu_name='sidebar')
register_multi_item_links(['metadatagroup_view', 'document_list', 'document_list_recent'], [document_multiple_clear_transformations, document_multiple_delete]) register_multi_item_links(['document_group_view', 'document_list', 'document_list_recent'], [document_multiple_clear_transformations, document_multiple_delete])
if ENABLE_SINGLE_DOCUMENT_UPLOAD: if ENABLE_SINGLE_DOCUMENT_UPLOAD:
register_links(['document_list_recent', 'document_list', 'document_create', 'document_create_multiple', 'upload_document_with_type', 'upload_multiple_documents_with_type'], [document_list_recent, document_list, document_create, document_create_multiple], menu_name='sidebar') register_links(['document_list_recent', 'document_list', 'document_create', 'document_create_multiple', 'upload_document_with_type', 'upload_multiple_documents_with_type'], [document_list_recent, document_list, document_create, document_create_multiple], menu_name='sidebar')
@@ -109,8 +109,6 @@ register_links(['document_page_transformation_edit', 'document_page_transformati
register_links(StagingFile, [staging_file_preview, staging_file_delete]) register_links(StagingFile, [staging_file_preview, staging_file_delete])
register_links(['metadatagroup_view'], [metadata_group_back_to_document, metadata_group_create_sibling], menu_name='sidebar')
register_diagnostic('documents', _(u'Documents'), document_missing_list) register_diagnostic('documents', _(u'Documents'), document_missing_list)
register_tool(document_find_all_duplicates, namespace='documents', title=_(u'documents')) register_tool(document_find_all_duplicates, namespace='documents', title=_(u'documents'))

View File

@@ -3,8 +3,8 @@ from django.contrib import admin
from metadata.admin import DocumentMetadataInline from metadata.admin import DocumentMetadataInline
from documents.models import DocumentType, Document, \ from documents.models import DocumentType, Document, \
DocumentTypeFilename, MetadataIndex, DocumentPage, DocumentGroup, \ DocumentTypeFilename, MetadataIndex, DocumentPage, \
DocumentGroupItem, DocumentPageTransformation, RecentDocument DocumentPageTransformation, RecentDocument
from filesystem_serving.admin import DocumentMetadataIndexInline from filesystem_serving.admin import DocumentMetadataIndexInline
@@ -48,18 +48,6 @@ class DocumentAdmin(admin.ModelAdmin):
list_display = ('uuid', 'file_filename', 'file_extension') list_display = ('uuid', 'file_filename', 'file_extension')
class DocumentGroupItemInline(admin.StackedInline):
model = DocumentGroupItem
extra = 1
classes = ('collapse-open',)
allow_add = True
class DocumentGroupAdmin(admin.ModelAdmin):
inlines = [DocumentGroupItemInline]
filter_horizontal = ['document_type']
class RecentDocumentAdmin(admin.ModelAdmin): class RecentDocumentAdmin(admin.ModelAdmin):
model = RecentDocument model = RecentDocument
list_display = ('user', 'document', 'datetime_accessed') list_display = ('user', 'document', 'datetime_accessed')
@@ -70,7 +58,6 @@ class RecentDocumentAdmin(admin.ModelAdmin):
admin.site.register(DocumentType, DocumentTypeAdmin) admin.site.register(DocumentType, DocumentTypeAdmin)
admin.site.register(Document, DocumentAdmin) admin.site.register(Document, DocumentAdmin)
admin.site.register(DocumentGroup, DocumentGroupAdmin)
admin.site.register(DocumentPageTransformation, admin.site.register(DocumentPageTransformation,
DocumentPageTransformationAdmin) DocumentPageTransformationAdmin)
admin.site.register(RecentDocument, RecentDocumentAdmin) admin.site.register(RecentDocument, RecentDocumentAdmin)

View File

@@ -60,7 +60,5 @@ register_settings(
{'name': u'ZOOM_MAX_LEVEL', 'global_name': u'DOCUMENTS_ZOOM_MAX_LEVEL', 'default': 200, 'description': _(u'Maximum amount in percent (%) to allow user to zoom in a document page interactively.')}, {'name': u'ZOOM_MAX_LEVEL', 'global_name': u'DOCUMENTS_ZOOM_MAX_LEVEL', 'default': 200, 'description': _(u'Maximum amount in percent (%) to allow user to zoom in a document page interactively.')},
{'name': u'ZOOM_MIN_LEVEL', 'global_name': u'DOCUMENTS_ZOOM_MIN_LEVEL', 'default': 50, 'description': _(u'Minimum amount in percent (%) to allow user to zoom out a document page interactively.')}, {'name': u'ZOOM_MIN_LEVEL', 'global_name': u'DOCUMENTS_ZOOM_MIN_LEVEL', 'default': 50, 'description': _(u'Minimum amount in percent (%) to allow user to zoom out a document page interactively.')},
{'name': u'ROTATION_STEP', 'global_name': u'DOCUMENTS_ROTATION_STEP', 'default': 90, 'description': _(u'Amount in degrees to rotate a document page per user interaction.')}, {'name': u'ROTATION_STEP', 'global_name': u'DOCUMENTS_ROTATION_STEP', 'default': 90, 'description': _(u'Amount in degrees to rotate a document page per user interaction.')},
#Groups
{'name': u'GROUP_SHOW_EMPTY', 'global_name': u'DOCUMENTS_GROUP_SHOW_EMPTY', 'default': True},
] ]
) )

View File

@@ -118,7 +118,7 @@ class ImageWidget(forms.widgets.Widget):
for page in value.documentpage_set.all(): for page in value.documentpage_set.all():
output.append( output.append(
u'''<div style="display: inline-block; margin: 5px 10px 0px 10px;"> u'''<div style="display: inline-block; margin: 5px 10px 10px 10px;">
<div class="tc">%(page_string)s %(page)s</div> <div class="tc">%(page_string)s %(page)s</div>
<div class="tc" style="border: 1px solid black; margin: 5px 0px 5px 0px;"> <div class="tc" style="border: 1px solid black; margin: 5px 0px 5px 0px;">
<a rel="page_gallery" class="fancybox-noscaling" href="%(view_url)s?page=%(page)d"> <a rel="page_gallery" class="fancybox-noscaling" href="%(view_url)s?page=%(page)d">
@@ -325,85 +325,6 @@ class DocumentCreateWizard(BoundFormWizard):
return HttpResponseRedirect(url) return HttpResponseRedirect(url)
class MetaDataImageWidget(forms.widgets.Widget):
def render(self, name, value, attrs=None):
output = []
if value['links']:
output.append(u'<div class="group navform wat-cf">')
for link in value['links']:
output.append(u'''
<button class="button" type="submit" name="action" value="%(action)s">
<span class="famfam active famfam-%(famfam)s"></span>%(text)s
</button>
''' % {
'famfam': link.get('famfam', u'link'),
'text': capfirst(link['text']),
'action': reverse('metadatagroup_view', args=[value['current_document'].pk, value['group'].pk])
})
output.append(u'</div>')
output.append(u'<div style="white-space:nowrap; overflow: auto;">')
for document in value['group_data']:
tags_template = get_tags_inline_widget(document)
output.append(
u'''<div style="display: inline-block; margin: 10px; %(current)s">
<div class="tc">%(document_name)s</div>
<div class="tc">%(page_string)s: %(document_pages)d</div>
%(tags_template)s
<div class="tc">
<a rel="group_%(group_id)d_documents_gallery" class="fancybox-noscaling" href="%(view_url)s">
<img class="lazy-load" style="border: 1px solid black; margin: 10px;" src="%(media_url)s/images/ajax-loader.gif" data-href="%(img)s" alt="%(string)s" />
<noscript>
<img style="border: 1px solid black; margin: 10px;" src="%(img)s" alt="%(string)s" />
</noscript>
</a>
</div>
<div class="tc">
<a href="%(url)s"><span class="famfam active famfam-page_go"></span>%(details_string)s</a>
</div>
</div>''' % {
'url': reverse('document_view_simple', args=[document.pk]),
'img': reverse('document_preview_multipage', args=[document.pk]),
'current': u'border: 5px solid black; padding: 3px;' if value['current_document'] == document else u'',
'view_url': reverse('document_display', args=[document.pk]),
'document_pages': document.documentpage_set.count(),
'page_string': ugettext(u'Pages'),
'details_string': ugettext(u'Select'),
'group_id': value['group'].pk,
'document_name': document,
'media_url': settings.MEDIA_URL,
'tags_template': tags_template if tags_template else u'',
'string': _(u'group document'),
})
output.append(u'</div>')
output.append(
u'<br /><span class="famfam active famfam-magnifier"></span>%s' %
ugettext(u'Click on the image for full size view of the first page.'))
return mark_safe(u''.join(output))
class MetaDataGroupForm(forms.Form):
def __init__(self, *args, **kwargs):
groups = kwargs.pop('groups', None)
links = kwargs.pop('links', None)
current_document = kwargs.pop('current_document', None)
super(MetaDataGroupForm, self).__init__(*args, **kwargs)
for group, data in groups.items():
self.fields['preview-%s' % group] = forms.CharField(
widget=MetaDataImageWidget(),
label=u'%s (%d)' % (unicode(group), len(data)),
required=False,
initial={
'group': group,
'group_data': data,
'current_document': current_document,
'links': links
}
)
class PrintForm(forms.Form): class PrintForm(forms.Form):
page_size = forms.ChoiceField(choices=PAGE_SIZE_CHOICES, initial=DEFAULT_PAPER_SIZE, label=_(u'Page size'), required=False) page_size = forms.ChoiceField(choices=PAGE_SIZE_CHOICES, initial=DEFAULT_PAPER_SIZE, label=_(u'Page size'), required=False)
custom_page_width = forms.CharField(label=_(u'Custom page width'), required=False) custom_page_width = forms.CharField(label=_(u'Custom page width'), required=False)

View File

@@ -2,3 +2,12 @@ PICTURE_ERROR_SMALL = u'picture_error.png'
PICTURE_ERROR_MEDIUM = u'1297211435_error.png' PICTURE_ERROR_MEDIUM = u'1297211435_error.png'
PICTURE_UNKNOWN_SMALL = u'1299549572_unknown2.png' PICTURE_UNKNOWN_SMALL = u'1299549572_unknown2.png'
PICTURE_UNKNOWN_MEDIUM = u'1299549805_unknown.png' PICTURE_UNKNOWN_MEDIUM = u'1299549805_unknown.png'
PERMISSION_DOCUMENT_CREATE = 'document_create'
PERMISSION_DOCUMENT_PROPERTIES_EDIT = 'document_properties_edit'
PERMISSION_DOCUMENT_EDIT = 'document_edit'
PERMISSION_DOCUMENT_VIEW = 'document_view'
PERMISSION_DOCUMENT_DELETE = 'document_delete'
PERMISSION_DOCUMENT_DOWNLOAD = 'document_download'
PERMISSION_DOCUMENT_TRANSFORM = 'document_transform'
PERMISSION_DOCUMENT_TOOLS = 'document_tools'

View File

@@ -1,52 +0,0 @@
from django.db import models
#from documents.models import DocumentGroup
from metadata.classes import MetadataObject
class DocumentGroupManager(models.Manager):
def get_groups_for(self, document, group_obj=None):
errors = []
metadata_groups = {}
metadata_dict = {}
for document_metadata in document.documentmetadata_set.all():
metadata_dict[document_metadata.metadata_type.name] = document_metadata.value
eval_dict = {}
eval_dict['document'] = document
eval_dict['metadata'] = MetadataObject(metadata_dict)
#if group_obj:
# groups_qs = DocumentGroup.objects.filter((Q(document_type=document.document_type) | Q(document_type=None)) & Q(enabled=True) & Q(pk=group_obj.pk))
#else:
# groups_qs = DocumentGroup.objects.filter((Q(document_type=document.document_type) | Q(document_type=None)) & Q(enabled=True))
groups_qs=[]
for group in groups_qs:
total_query = Q()
for item in group.metadatagroupitem_set.filter(enabled=True):
try:
value_query = Q(**{'value__%s' % item.operator: eval(item.expression, eval_dict)})
if item.negated:
query = (Q(metadata_type__id=item.metadata_type_id) & ~value_query)
else:
query = (Q(metadata_type__id=item.metadata_type_id) & value_query)
if item.inclusion == INCLUSION_AND:
total_query &= query
elif item.inclusion == INCLUSION_OR:
total_query |= query
except Exception, e:
errors.append(e)
value_query = Q()
query = Q()
if total_query:
document_id_list = DocumentMetadata.objects.filter(total_query).values_list('document', flat=True)
metadata_groups[group] = Document.objects.filter(Q(id__in=document_id_list)).order_by('file_filename') or []
else:
metadata_groups[group] = []
if group_obj:
return metadata_groups[group_obj], errors
return metadata_groups, errors

View File

@@ -24,7 +24,6 @@ from documents.conf.settings import STORAGE_BACKEND
from documents.conf.settings import AVAILABLE_TRANSFORMATIONS from documents.conf.settings import AVAILABLE_TRANSFORMATIONS
from documents.conf.settings import DEFAULT_TRANSFORMATIONS from documents.conf.settings import DEFAULT_TRANSFORMATIONS
from documents.conf.settings import RECENT_COUNT from documents.conf.settings import RECENT_COUNT
from documents.managers import DocumentGroupManager
def get_filename_from_uuid(instance, filename): def get_filename_from_uuid(instance, filename):
filename, extension = os.path.splitext(filename) filename, extension = os.path.splitext(filename)
@@ -187,9 +186,6 @@ class Document(models.Model):
""" """
return u', '.join([u'%s - %s' % (metadata.metadata_type, metadata.value) for metadata in self.documentmetadata_set.select_related('metadata_type', 'document').defer('document__document_type', 'document__file', 'document__description', 'document__file_filename', 'document__uuid', 'document__date_added', 'document__date_updated', 'document__file_mimetype', 'document__file_mime_encoding')]) return u', '.join([u'%s - %s' % (metadata.metadata_type, metadata.value) for metadata in self.documentmetadata_set.select_related('metadata_type', 'document').defer('document__document_type', 'document__file', 'document__description', 'document__file_filename', 'document__uuid', 'document__date_added', 'document__date_updated', 'document__file_mimetype', 'document__file_mime_encoding')])
def get_metadata_groups(self, group_obj=None):
return DocumentGroup.objects.get_groups_for(self, group_obj)
def apply_default_transformations(self): def apply_default_transformations(self):
#Only apply default transformations on new documents #Only apply default transformations on new documents
if DEFAULT_TRANSFORMATIONS and reduce(lambda x, y: x + y, [page.documentpagetransformation_set.count() for page in self.documentpage_set.all()]) == 0: if DEFAULT_TRANSFORMATIONS and reduce(lambda x, y: x + y, [page.documentpagetransformation_set.count() for page in self.documentpage_set.all()]) == 0:
@@ -276,68 +272,7 @@ class DocumentPage(models.Model):
return ' '.join(transformation_list), warnings return ' '.join(transformation_list), warnings
class DocumentGroup(models.Model):
document_type = models.ManyToManyField(DocumentType, null=True, blank=True,
verbose_name=_(u'document type'), help_text=_(u'If left blank, all document types will be matched.'))
label = models.CharField(max_length=32, verbose_name=_(u'label'))
enabled = models.BooleanField(default=True, verbose_name=_(u'enabled'))
objects = DocumentGroupManager()
def __unicode__(self):
return self.label if self.label else self.name
class Meta:
verbose_name = _(u'document group')
verbose_name_plural = _(u'document groups')
INCLUSION_AND = u'&'
INCLUSION_OR = u'|'
INCLUSION_CHOICES = (
(INCLUSION_AND, _(u'and')),
(INCLUSION_OR, _(u'or')),
)
OPERATOR_CHOICES = (
(u'exact', _(u'is equal')),
(u'iexact', _(u'is equal (case insensitive)')),
(u'contains', _(u'contains')),
(u'icontains', _(u'contains (case insensitive)')),
(u'in', _(u'is in')),
(u'gt', _(u'is greater than')),
(u'gte', _(u'is greater than or equal')),
(u'lt', _(u'is less than')),
(u'lte', _(u'is less than or equal')),
(u'startswith', _(u'starts with')),
(u'istartswith', _(u'starts with (case insensitive)')),
(u'endswith', _(u'ends with')),
(u'iendswith', _(u'ends with (case insensitive)')),
(u'regex', _(u'is in regular expression')),
(u'iregex', _(u'is in regular expression (case insensitive)')),
)
#LOCAL_SOURCE_CHOICES = (
# (u'
class DocumentGroupItem(models.Model):
metadata_group = models.ForeignKey(DocumentGroup, verbose_name=_(u'metadata group'))
inclusion = models.CharField(default=INCLUSION_AND, max_length=16, choices=INCLUSION_CHOICES, help_text=_(u'The inclusion is ignored for the first item.'))
#foreign_metadata_type = models.ForeignKey(MetadataType, related_name='metadata_type_foreign', verbose_name=_(u'foreign metadata'), help_text=_(u'This represents the metadata of all other documents.'))
operator = models.CharField(max_length=16, choices=OPERATOR_CHOICES)
#local_metadata_type = models.ForeignKey(MetadataType, related_name='metadata_type_local', verbose_name=_(u'local metadata'), help_text=_(u'This represents the metadata of the current document.'))
expression = models.TextField(verbose_name=_(u'expression'), help_text=_(u'This expression will be evaluated against the current selected document. The document metadata is available as variables `metadata` and document properties under the variable `document`.'))
negated = models.BooleanField(default=False, verbose_name=_(u'negated'), help_text=_(u'Inverts the logic of the operator.'))
enabled = models.BooleanField(default=True, verbose_name=_(u'enabled'))
def __unicode__(self):
return u'[%s] %s %s %s %s %s' % (u'x' if self.enabled else u' ', self.get_inclusion_display(), self.metadata_type, _(u'not') if self.negated else u'', self.get_operator_display(), self.expression)
class Meta:
verbose_name = _(u'group item')
verbose_name_plural = _(u'group items')
available_transformations = ([(name, data['label']) for name, data in AVAILABLE_TRANSFORMATIONS.items()]) available_transformations = ([(name, data['label']) for name, data in AVAILABLE_TRANSFORMATIONS.items()])

View File

@@ -34,7 +34,6 @@ urlpatterns = patterns('documents.views',
url(r'^document/(?P<document_id>\d+)/create/siblings/$', 'document_create_sibling', {'multiple': True if ENABLE_SINGLE_DOCUMENT_UPLOAD == False else False}, 'document_create_sibling'), url(r'^document/(?P<document_id>\d+)/create/siblings/$', 'document_create_sibling', {'multiple': True if ENABLE_SINGLE_DOCUMENT_UPLOAD == False else False}, 'document_create_sibling'),
url(r'^document/(?P<document_id>\d+)/find_duplicates/$', 'document_find_duplicates', (), 'document_find_duplicates'), url(r'^document/(?P<document_id>\d+)/find_duplicates/$', 'document_find_duplicates', (), 'document_find_duplicates'),
url(r'^document/(?P<document_id>\d+)/clear_transformations/$', 'document_clear_transformations', (), 'document_clear_transformations'), url(r'^document/(?P<document_id>\d+)/clear_transformations/$', 'document_clear_transformations', (), 'document_clear_transformations'),
url(r'^document/(?P<document_id>\d+)/group/(?P<metadata_group_id>\d+)/$', 'metadatagroup_view', (), 'metadatagroup_view'),
url(r'^document/multiple/clear_transformations/$', 'document_multiple_clear_transformations', (), 'document_multiple_clear_transformations'), url(r'^document/multiple/clear_transformations/$', 'document_multiple_clear_transformations', (), 'document_multiple_clear_transformations'),
url(r'^duplicates/$', 'document_find_all_duplicates', (), 'document_find_all_duplicates'), url(r'^duplicates/$', 'document_find_all_duplicates', (), 'document_find_all_duplicates'),
@@ -61,6 +60,4 @@ urlpatterns = patterns('documents.views',
url(r'^document/page/transformation/(?P<document_page_transformation_id>\d+)/delete/$', 'document_page_transformation_delete', (), 'document_page_transformation_delete'), url(r'^document/page/transformation/(?P<document_page_transformation_id>\d+)/delete/$', 'document_page_transformation_delete', (), 'document_page_transformation_delete'),
url(r'^document/missing/list/$', 'document_missing_list', (), 'document_missing_list'), url(r'^document/missing/list/$', 'document_missing_list', (), 'document_missing_list'),
url(r'^metadatagroup_action/action/$', 'metadatagroup_action', (), 'metadatagroup_action'),
) )

View File

@@ -17,29 +17,31 @@ from django.contrib.comments.models import Comment
import sendfile import sendfile
from common.utils import pretty_size, parse_range, urlquote from common.utils import pretty_size, parse_range, urlquote
from converter.api import convert_document, QUALITY_DEFAULT
from converter.exceptions import UnkownConvertError, UnknownFormat
from filetransfers.api import serve_file
from filesystem_serving.api import document_create_fs_links, document_delete_fs_links
from filesystem_serving.conf.settings import FILESERVING_ENABLE
from permissions.api import check_permissions
from navigation.utils import resolve_to_name
from tags.utils import get_tags_subtemplate
from document_comments.utils import get_comments_subtemplate
from converter.api import DEFAULT_ZOOM_LEVEL, DEFAULT_ROTATION, \
DEFAULT_FILE_FORMAT, QUALITY_PRINT
from common.literals import PAGE_SIZE_DIMENSIONS, \ from common.literals import PAGE_SIZE_DIMENSIONS, \
PAGE_ORIENTATION_PORTRAIT, PAGE_ORIENTATION_LANDSCAPE PAGE_ORIENTATION_PORTRAIT, PAGE_ORIENTATION_LANDSCAPE
from common.conf.settings import DEFAULT_PAPER_SIZE from common.conf.settings import DEFAULT_PAPER_SIZE
from converter.api import convert_document, QUALITY_DEFAULT
from converter.exceptions import UnkownConvertError, UnknownFormat
from converter.api import DEFAULT_ZOOM_LEVEL, DEFAULT_ROTATION, \
DEFAULT_FILE_FORMAT, QUALITY_PRINT
from document_comments.utils import get_comments_subtemplate
from filesystem_serving.api import document_create_fs_links, document_delete_fs_links
from filesystem_serving.conf.settings import FILESERVING_ENABLE
from filetransfers.api import serve_file
from grouping.models import DocumentGroup
from grouping import document_group_link
from grouping.utils import get_document_group_subtemplate
from metadata.api import save_metadata_list, \ from metadata.api import save_metadata_list, \
decode_metadata_from_url, metadata_repr_as_list decode_metadata_from_url, metadata_repr_as_list
from metadata.forms import MetadataFormSet from metadata.forms import MetadataFormSet
from navigation.utils import resolve_to_name
from permissions.api import check_permissions
from tags.utils import get_tags_subtemplate
from documents.conf.settings import DELETE_STAGING_FILE_AFTER_UPLOAD from documents.conf.settings import DELETE_STAGING_FILE_AFTER_UPLOAD
from documents.conf.settings import USE_STAGING_DIRECTORY from documents.conf.settings import USE_STAGING_DIRECTORY
from documents.conf.settings import PREVIEW_SIZE from documents.conf.settings import PREVIEW_SIZE
from documents.conf.settings import THUMBNAIL_SIZE from documents.conf.settings import THUMBNAIL_SIZE
from documents.conf.settings import GROUP_SHOW_EMPTY
from documents.conf.settings import UNCOMPRESS_COMPRESSED_LOCAL_FILES from documents.conf.settings import UNCOMPRESS_COMPRESSED_LOCAL_FILES
from documents.conf.settings import UNCOMPRESS_COMPRESSED_STAGING_FILES from documents.conf.settings import UNCOMPRESS_COMPRESSED_STAGING_FILES
from documents.conf.settings import STORAGE_BACKEND from documents.conf.settings import STORAGE_BACKEND
@@ -49,7 +51,7 @@ from documents.conf.settings import ZOOM_MIN_LEVEL
from documents.conf.settings import ROTATION_STEP from documents.conf.settings import ROTATION_STEP
from documents.conf.settings import PRINT_SIZE from documents.conf.settings import PRINT_SIZE
from documents import PERMISSION_DOCUMENT_CREATE, \ from documents.literals import PERMISSION_DOCUMENT_CREATE, \
PERMISSION_DOCUMENT_PROPERTIES_EDIT, \ PERMISSION_DOCUMENT_PROPERTIES_EDIT, \
PERMISSION_DOCUMENT_VIEW, \ PERMISSION_DOCUMENT_VIEW, \
PERMISSION_DOCUMENT_DELETE, PERMISSION_DOCUMENT_DOWNLOAD, \ PERMISSION_DOCUMENT_DELETE, PERMISSION_DOCUMENT_DOWNLOAD, \
@@ -60,13 +62,12 @@ from documents.forms import DocumentTypeSelectForm, DocumentCreateWizard, \
DocumentForm, DocumentForm_edit, DocumentForm_view, \ DocumentForm, DocumentForm_edit, DocumentForm_view, \
StagingDocumentForm, DocumentPreviewForm, \ StagingDocumentForm, DocumentPreviewForm, \
DocumentPageForm, DocumentPageTransformationForm, \ DocumentPageForm, DocumentPageTransformationForm, \
DocumentContentForm, DocumentPageForm_edit, MetaDataGroupForm, \ DocumentContentForm, DocumentPageForm_edit, \
DocumentPageForm_text, PrintForm, MetadataSelectionForm DocumentPageForm_text, PrintForm, MetadataSelectionForm
from documents.models import Document, DocumentType, DocumentPage, \ from documents.models import Document, DocumentType, DocumentPage, \
DocumentPageTransformation, RecentDocument, DocumentGroup DocumentPageTransformation, RecentDocument
from documents.staging import StagingFile from documents.staging import StagingFile
from documents import metadata_group_link
from documents.literals import PICTURE_ERROR_SMALL, PICTURE_ERROR_MEDIUM, \ from documents.literals import PICTURE_ERROR_SMALL, PICTURE_ERROR_MEDIUM, \
PICTURE_UNKNOWN_SMALL, PICTURE_UNKNOWN_MEDIUM PICTURE_UNKNOWN_SMALL, PICTURE_UNKNOWN_MEDIUM
@@ -314,33 +315,10 @@ def document_view_simple(request, document_id):
}, },
) )
metadata_groups, errors = document.get_metadata_groups() document_group_subtemplate = get_document_group_subtemplate(request, document)
if (request.user.is_staff or request.user.is_superuser) and errors:
for error in errors:
messages.warning(request, _(u'Document group query error: %s' % error))
if not GROUP_SHOW_EMPTY: if document_group_subtemplate:
#If GROUP_SHOW_EMPTY is False, remove empty groups from subtemplates_list.append(document_group_subtemplate)
#dictionary
metadata_groups = dict([(group, data) for group, data in metadata_groups.items() if data])
if metadata_groups:
subtemplates_list.append(
{
'name': 'generic_form_subtemplate.html',
'context': {
'title': _(u'document groups (%s)') % len(metadata_groups.keys()),
'form': MetaDataGroupForm(
groups=metadata_groups, current_document=document,
links=[
metadata_group_link
]
),
'form_action': reverse('metadatagroup_action'),
'submit_method': 'GET',
}
}
)
return render_to_response('generic_detail.html', { return render_to_response('generic_detail.html', {
'object': document, 'object': document,
@@ -413,30 +391,10 @@ def document_view_advanced(request, document_id):
}, },
) )
metadata_groups, errors = document.get_metadata_groups() document_group_subtemplate = get_document_group_subtemplate(request, document)
if (request.user.is_staff or request.user.is_superuser) and errors:
for error in errors:
messages.warning(request, _(u'Document group query error: %s' % error))
if not GROUP_SHOW_EMPTY: if document_group_subtemplate:
#If GROUP_SHOW_EMPTY is False, remove empty groups from subtemplates_list.append(document_group_subtemplate)
#dictionary
metadata_groups = dict([(group, data) for group, data in metadata_groups.items() if data])
if metadata_groups:
subtemplates_list.append(
{
'name': 'generic_form_subtemplate.html',
'context': {
'title': _(u'document groups (%s)') % len(metadata_groups.keys()),
'form': MetaDataGroupForm(groups=metadata_groups, current_document=document, links=[
metadata_group_link
]),
'form_action': reverse('metadatagroup_action'),
'submit_method': 'GET',
}
}
)
if FILESERVING_ENABLE: if FILESERVING_ENABLE:
subtemplates_list.append({ subtemplates_list.append({
@@ -1057,35 +1015,6 @@ def document_page_rotate_left(request, document_page_id):
) )
def metadatagroup_action(request):
action = request.GET.get('action', None)
if not action:
messages.error(request, _(u'No action selected.'))
return HttpResponseRedirect(request.META.get('HTTP_REFERER', u'/'))
return HttpResponseRedirect(action)
def metadatagroup_view(request, document_id, metadata_group_id):
check_permissions(request.user, 'documents', [PERMISSION_DOCUMENT_VIEW])
document = get_object_or_404(Document, pk=document_id)
metadata_group = get_object_or_404(MetadataGroup, pk=metadata_group_id)
object_list, errors = document.get_metadata_groups(metadata_group)
return render_to_response('generic_list.html', {
'object_list': object_list,
'title': _(u'documents in group: %(group)s, for document: %(document)s') % {
'group': metadata_group, 'document': document
},
'multi_select_as_buttons': True,
'hide_links': True,
'ref_object': document
}, context_instance=RequestContext(request))
def document_print(request, document_id): def document_print(request, document_id):
check_permissions(request.user, 'documents', [PERMISSION_DOCUMENT_VIEW]) check_permissions(request.user, 'documents', [PERMISSION_DOCUMENT_VIEW])

23
apps/grouping/__init__.py Normal file
View File

@@ -0,0 +1,23 @@
from django.utils.translation import ugettext_lazy as _
#from django.core.urlresolvers import reverse
#from django.conf import settings
from navigation.api import register_links, register_menu, \
register_model_list_columns, register_multi_item_links
from main.api import register_diagnostic, register_tool
from permissions.api import register_permissions
from tags.widgets import get_tags_inline_widget_simple
#from documents.models import Document, DocumentPage, DocumentPageTransformation
#from documents.staging import StagingFile
#from documents.conf.settings import ENABLE_SINGLE_DOCUMENT_UPLOAD
from documents.literals import PERMISSION_DOCUMENT_CREATE, PERMISSION_DOCUMENT_VIEW
#from documents import document_multiple_clear_transformations
document_group_link = {'text': _(u'group actions'), 'view': 'document_group_view', 'famfam': 'page_go', 'permissions': {'namespace': 'documents', 'permissions': [PERMISSION_DOCUMENT_VIEW]}}
document_group_back_to_document = {'text': _(u'return to document'), 'view': 'document_view_simple', 'args': 'ref_object.id', 'famfam': 'page', 'permissions': {'namespace': 'documents', 'permissions': [PERMISSION_DOCUMENT_VIEW]}}
document_group_create_sibling = {'text': _(u'upload new document using same metadata'), 'view': 'document_create_sibling', 'args': 'ref_object.id', 'famfam': 'page_copy', 'permissions': {'namespace': 'documents', 'permissions': [PERMISSION_DOCUMENT_CREATE]}}
#register_multi_item_links(['document_group_view'], [document_multiple_clear_transformations, document_multiple_delete])
register_links(['document_group_view'], [document_group_back_to_document, document_group_create_sibling], menu_name='sidebar')

16
apps/grouping/admin.py Normal file
View File

@@ -0,0 +1,16 @@
from django.contrib import admin
from grouping.models import DocumentGroup, DocumentGroupItem
class DocumentGroupItemInline(admin.StackedInline):
model = DocumentGroupItem
extra = 1
classes = ('collapse-open',)
allow_add = True
class DocumentGroupAdmin(admin.ModelAdmin):
inlines = [DocumentGroupItemInline]
admin.site.register(DocumentGroup, DocumentGroupAdmin)

View File

View File

@@ -0,0 +1,13 @@
"""Configuration options for the grouping app"""
from django.utils.translation import ugettext_lazy as _
from smart_settings.api import register_settings
register_settings(
namespace=u'grouping',
module=u'grouping.conf.settings',
settings=[
{'name': u'SHOW_EMPTY_GROUPS', 'global_name': u'GROUPING_SHOW_EMPTY_GROUPS', 'default': True},
]
)

103
apps/grouping/forms.py Normal file
View File

@@ -0,0 +1,103 @@
from django import forms
from django.utils.translation import ugettext_lazy as _
from django.utils.translation import ugettext
from django.http import HttpResponseRedirect
from django.utils.http import urlencode
from django.core.urlresolvers import reverse
from django.utils.safestring import mark_safe
from django.forms.formsets import formset_factory
from django.template.defaultfilters import capfirst
from django.conf import settings
from tags.widgets import get_tags_inline_widget
#from common.wizard import BoundFormWizard
#from common.forms import DetailForm
#from common.literals import PAGE_SIZE_CHOICES, PAGE_ORIENTATION_CHOICES
#from common.conf.settings import DEFAULT_PAPER_SIZE
#from common.conf.settings import DEFAULT_PAGE_ORIENTATION
#from common.utils import urlquote
#from metadata.models import MetadataSet, MetadataType
#from metadata.forms import MetadataFormSet
#from documents.staging import StagingFile
#from documents.models import Document, DocumentType, \
# DocumentPage, DocumentPageTransformation
class DocumentGroupImageWidget(forms.widgets.Widget):
def render(self, name, value, attrs=None):
output = []
if value['links']:
output.append(u'<div class="group navform wat-cf">')
for link in value['links']:
output.append(u'''
<button class="button" type="submit" name="action" value="%(action)s">
<span class="famfam active famfam-%(famfam)s"></span>%(text)s
</button>
''' % {
'famfam': link.get('famfam', u'link'),
'text': capfirst(link['text']),
'action': reverse('document_group_view', args=[value['current_document'].pk, value['group'].pk])
})
output.append(u'</div>')
output.append(u'<div style="white-space:nowrap; overflow: auto;">')
for document in value['group_data']:
tags_template = get_tags_inline_widget(document)
output.append(
u'''<div style="display: inline-block; margin: 0px 10px 10px 10px; %(current)s">
<div class="tc">%(document_name)s</div>
<div class="tc">%(page_string)s: %(document_pages)d</div>
%(tags_template)s
<div class="tc">
<a rel="group_%(group_id)d_documents_gallery" class="fancybox-noscaling" href="%(view_url)s">
<img class="lazy-load" style="border: 1px solid black; margin: 10px;" src="%(media_url)s/images/ajax-loader.gif" data-href="%(img)s" alt="%(string)s" />
<noscript>
<img style="border: 1px solid black; margin: 10px;" src="%(img)s" alt="%(string)s" />
</noscript>
</a>
</div>
<div class="tc">
<a href="%(url)s"><span class="famfam active famfam-page_go"></span>%(details_string)s</a>
</div>
</div>''' % {
'url': reverse('document_view_simple', args=[document.pk]),
'img': reverse('document_preview_multipage', args=[document.pk]),
'current': u'border: 5px solid black; padding: 3px;' if value['current_document'] == document else u'',
'view_url': reverse('document_display', args=[document.pk]),
'document_pages': document.documentpage_set.count(),
'page_string': ugettext(u'Pages'),
'details_string': ugettext(u'Select'),
'group_id': value['group'].pk,
'document_name': document,
'media_url': settings.MEDIA_URL,
'tags_template': tags_template if tags_template else u'',
'string': _(u'group document'),
})
output.append(u'</div>')
output.append(
u'<br /><span class="famfam active famfam-magnifier"></span>%s' %
ugettext(u'Click on the image for full size view of the first page.'))
return mark_safe(u''.join(output))
class DocumentDataGroupForm(forms.Form):
def __init__(self, *args, **kwargs):
groups = kwargs.pop('groups', None)
links = kwargs.pop('links', None)
current_document = kwargs.pop('current_document', None)
super(DocumentDataGroupForm, self).__init__(*args, **kwargs)
for group, data in groups.items():
self.fields['preview-%s' % group] = forms.CharField(
widget=DocumentGroupImageWidget(),
label=u'%s (%d)' % (unicode(data['title']), len(data['documents'])),
required=False,
initial={
'group': group,
'group_data': data['documents'],
'current_document': current_document,
'links': links
}
)

27
apps/grouping/literals.py Normal file
View File

@@ -0,0 +1,27 @@
from django.utils.translation import ugettext_lazy as _
INCLUSION_AND = u'&'
INCLUSION_OR = u'|'
INCLUSION_CHOICES = (
(INCLUSION_AND, _(u'and')),
(INCLUSION_OR, _(u'or')),
)
OPERATOR_CHOICES = (
(u'exact', _(u'is equal to')),
(u'iexact', _(u'is equal to (case insensitive)')),
(u'contains', _(u'contains')),
(u'icontains', _(u'contains (case insensitive)')),
(u'in', _(u'is in')),
(u'gt', _(u'is greater than')),
(u'gte', _(u'is greater than or equal to')),
(u'lt', _(u'is less than')),
(u'lte', _(u'is less than or equal to')),
(u'startswith', _(u'starts with')),
(u'istartswith', _(u'starts with (case insensitive)')),
(u'endswith', _(u'ends with')),
(u'iendswith', _(u'ends with (case insensitive)')),
(u'regex', _(u'is in regular expression')),
(u'iregex', _(u'is in regular expression (case insensitive)')),
)

86
apps/grouping/managers.py Normal file
View File

@@ -0,0 +1,86 @@
from django.db import models
from django.db.models import Q
from metadata.classes import MetadataObject
from metadata.models import DocumentMetadata
from documents.models import Document
from grouping.literals import INCLUSION_AND, INCLUSION_OR
class DocumentGroupManager(models.Manager):
def get_groups_for(self, document, group_obj=None):
errors = []
document_groups = {}
metadata_dict = {}
for document_metadata in document.documentmetadata_set.all():
metadata_dict[document_metadata.metadata_type.name] = document_metadata.value
eval_dict = {}
eval_dict['document'] = document
eval_dict['metadata'] = MetadataObject(metadata_dict)
if group_obj:
groups_qs = self.model.objects.filter(Q(enabled=True) & Q(pk=group_obj.pk))
else:
groups_qs = self.model.objects.filter(enabled=True)
for group in groups_qs:
total_query = Q()
for item in group.documentgroupitem_set.filter(enabled=True):
cls, attribute = item.foreign_document_data.lower().split(u'.')
try:
if cls == u'metadata':
value_query = Q(**{'documentmetadata__value__%s' % item.operator: eval(item.expression, eval_dict)})
if item.negated:
query = (Q(documentmetadata__metadata_type__name=attribute) & ~value_query)
else:
query = (Q(documentmetadata__metadata_type__name=attribute) & value_query)
if item.inclusion == INCLUSION_AND:
total_query &= query
elif item.inclusion == INCLUSION_OR:
total_query |= query
elif cls == u'document':
value_query = Q(**{
'%s__%s' % (attribute, item.operator): eval(item.expression, eval_dict)
})
if item.negated:
#query = (Q(metadata_type__name=attribute) & ~value_query)
query = ~value_query
else:
#query = (Q(metadata_type__name=attribute) & value_query)
query = value_query
if item.inclusion == INCLUSION_AND:
total_query &= query
elif item.inclusion == INCLUSION_OR:
total_query |= query
except Exception, e:
errors.append(e)
value_query = Q()
query = Q()
print 'total_query', total_query
if total_query:
try:
document_qs = Document.objects.filter(total_query)
document_groups[group] = {'documents': document_qs.order_by('file_filename') or []}
except Exception, e:
document_groups[group] = {'documents': []}
errors.append(e)
else:
document_groups[group] = {'documents': []}
if group.dynamic_title:
try:
document_groups[group]['title'] = eval(group.dynamic_title, eval_dict)
except Exception, e:
document_groups[group]['title'] = 'Error; %s' % e
else:
document_groups[group]['title'] = group.title
if group_obj:
# Return a single group if documents even if there were
# many matches
return document_groups[group_obj], errors
return document_groups, errors

42
apps/grouping/models.py Normal file
View File

@@ -0,0 +1,42 @@
from django.db import models
from django.utils.translation import ugettext_lazy as _
from documents.models import Document
from grouping.managers import DocumentGroupManager
from grouping.literals import OPERATOR_CHOICES, INCLUSION_AND, \
INCLUSION_CHOICES
class DocumentGroup(models.Model):
title = models.CharField(max_length=96, verbose_name=_(u'title'))
dynamic_title = models.CharField(blank=True, max_length=96, verbose_name=_(u'dynamic title'))
enabled = models.BooleanField(default=True, verbose_name=_(u'enabled'))
objects = DocumentGroupManager()
def __unicode__(self):
return self.title
class Meta:
verbose_name = _(u'document group')
verbose_name_plural = _(u'document groups')
class DocumentGroupItem(models.Model):
metadata_group = models.ForeignKey(DocumentGroup, verbose_name=_(u'metadata group'))
inclusion = models.CharField(default=INCLUSION_AND, max_length=16, choices=INCLUSION_CHOICES, help_text=_(u'The inclusion is ignored for the first item.'))
foreign_document_data = models.CharField(max_length=32, verbose_name=_(u'foreign document data'), help_text=_(u'This represents the metadata of all other documents. Available objects: `document.<attribute>` and `metadata.<metadata_type_name>`.'))
operator = models.CharField(max_length=16, choices=OPERATOR_CHOICES)
#local_document_data = models.ForeignKey(MetadataType, related_name='metadata_type_local', verbose_name=_(u'local metadata'), help_text=_(u'This represents the metadata of the current document.'))
expression = models.TextField(verbose_name=_(u'expression'), help_text=_(u'This expression will be evaluated against the current selected document. The document metadata is available as variables `metadata` and document properties under the variable `document`.'))
negated = models.BooleanField(default=False, verbose_name=_(u'negated'), help_text=_(u'Inverts the logic of the operator.'))
enabled = models.BooleanField(default=True, verbose_name=_(u'enabled'))
def __unicode__(self):
return u'[%s] %s foreign %s %s %s %s' % (u'x' if self.enabled else u' ', self.get_inclusion_display(), self.foreign_document_data, _(u'not') if self.negated else u'', self.get_operator_display(), self.expression)
class Meta:
verbose_name = _(u'group item')
verbose_name_plural = _(u'group items')

23
apps/grouping/tests.py Normal file
View File

@@ -0,0 +1,23 @@
"""
This file demonstrates two different styles of tests (one doctest and one
unittest). These will both pass when you run "manage.py test".
Replace these with more appropriate tests for your application.
"""
from django.test import TestCase
class SimpleTest(TestCase):
def test_basic_addition(self):
"""
Tests that 1 + 1 always equals 2.
"""
self.failUnlessEqual(1 + 1, 2)
__test__ = {"doctest": """
Another way to test that 1 + 1 is equal to 2.
>>> 1 + 1 == 2
True
"""}

6
apps/grouping/urls.py Normal file
View File

@@ -0,0 +1,6 @@
from django.conf.urls.defaults import patterns, url
urlpatterns = patterns('grouping.views',
url(r'^action/$', 'document_group_action', (), 'document_group_action'),
url(r'^document/(?P<document_id>\d+)/group/(?P<document_group_id>\d+)/$', 'document_group_view', (), 'document_group_view'),
)

36
apps/grouping/utils.py Normal file
View File

@@ -0,0 +1,36 @@
from django.utils.translation import ugettext_lazy as _
from django.contrib import messages
from django.core.urlresolvers import reverse
from grouping.models import DocumentGroup
from grouping.conf.settings import SHOW_EMPTY_GROUPS
from grouping.forms import DocumentDataGroupForm
from grouping import document_group_link
def get_document_group_subtemplate(request, document):
document_groups, errors = DocumentGroup.objects.get_groups_for(document)
if (request.user.is_staff or request.user.is_superuser) and errors:
for error in errors:
messages.warning(request, _(u'Document group query error: %s' % error))
if not SHOW_EMPTY_GROUPS:
#If GROUP_SHOW_EMPTY is False, remove empty groups from
#dictionary
document_groups = dict([(group, data) for group, data in document_groups.items() if data['documents']])
if document_groups:
return {
'name': 'generic_form_subtemplate.html',
'context': {
'title': _(u'document groups (%s)') % len(document_groups.keys()),
'form': DocumentDataGroupForm(
groups=document_groups, current_document=document,
links=[document_group_link]
),
'form_action': reverse('document_group_action'),
'submit_method': 'GET',
}
}
else:
return None

41
apps/grouping/views.py Normal file
View File

@@ -0,0 +1,41 @@
from django.utils.translation import ugettext_lazy as _
from django.contrib import messages
from django.http import HttpResponseRedirect
from django.shortcuts import render_to_response, get_object_or_404
from django.template import RequestContext
from documents.literals import PERMISSION_DOCUMENT_VIEW
from documents.models import Document
from documents.views import document_list
from permissions.api import check_permissions
from grouping.models import DocumentGroup
def document_group_action(request):
action = request.GET.get('action', None)
if not action:
messages.error(request, _(u'No action selected.'))
return HttpResponseRedirect(request.META.get('HTTP_REFERER', u'/'))
return HttpResponseRedirect(action)
def document_group_view(request, document_id, document_group_id):
check_permissions(request.user, 'documents', [PERMISSION_DOCUMENT_VIEW])
document = get_object_or_404(Document, pk=document_id)
document_group = get_object_or_404(DocumentGroup, pk=document_group_id)
object_list, errors = DocumentGroup.objects.get_groups_for(document, document_group)
#object_list, errors = document.get_metadata_groups(document_group)
return render_to_response('generic_list.html', {
'object_list': object_list['documents'],
'title': _(u'documents in group: %(group)s') % {
'group': object_list['title']
},
'multi_select_as_buttons': True,
'hide_links': True,
'ref_object': document
}, context_instance=RequestContext(request))

View File

@@ -25,4 +25,4 @@ metadata_remove = {'text': _(u'remove metadata'), 'view': 'metadata_remove', 'ar
metadata_multiple_remove = {'text': _(u'remove metadata'), 'view': 'metadata_multiple_remove', 'famfam': 'xhtml_delete', 'permissions': {'namespace': 'metadata', 'permissions': [PERMISSION_METADATA_DOCUMENT_REMOVE]}} metadata_multiple_remove = {'text': _(u'remove metadata'), 'view': 'metadata_multiple_remove', 'famfam': 'xhtml_delete', 'permissions': {'namespace': 'metadata', 'permissions': [PERMISSION_METADATA_DOCUMENT_REMOVE]}}
register_links(Document, [metadata_add, metadata_edit, metadata_remove]) register_links(Document, [metadata_add, metadata_edit, metadata_remove])
register_multi_item_links(['metadatagroup_view', 'document_list', 'document_list_recent'], [metadata_multiple_add, metadata_multiple_edit, metadata_multiple_remove]) register_multi_item_links(['document_datagroup_view', 'document_list', 'document_list_recent'], [metadata_multiple_add, metadata_multiple_edit, metadata_multiple_remove])

View File

@@ -146,6 +146,7 @@ INSTALLED_APPS = (
'document_comments', 'document_comments',
'user_management', 'user_management',
'documents', 'documents',
'grouping',
) )
TEMPLATE_CONTEXT_PROCESSORS = ( TEMPLATE_CONTEXT_PROCESSORS = (
@@ -212,8 +213,8 @@ TEMPLATE_CONTEXT_PROCESSORS = (
#DOCUMENTS_ZOOM_MIN_LEVEL = 50 #DOCUMENTS_ZOOM_MIN_LEVEL = 50
#DOCUMENTS_ROTATION_STEP = 90 #DOCUMENTS_ROTATION_STEP = 90
# Groups #------------- Groups --------------------
#DOCUMENTS_GROUP_SHOW_EMPTY = True #GROUPING_SHOW_EMPTY_GROUPS = True
#------------ Filesystem serving -------------- #------------ Filesystem serving --------------
#FILESYSTEM_FILESERVING_ENABLE = True #FILESYSTEM_FILESERVING_ENABLE = True
#FILESYSTEM_FILESERVING_PATH = u'/tmp/mayan/documents' #FILESYSTEM_FILESERVING_PATH = u'/tmp/mayan/documents'

View File

@@ -22,6 +22,7 @@ urlpatterns = patterns('',
(r'^user_management/', include('user_management.urls')), (r'^user_management/', include('user_management.urls')),
(r'^settings/', include('smart_settings.urls')), (r'^settings/', include('smart_settings.urls')),
(r'^metadata/', include('metadata.urls')), (r'^metadata/', include('metadata.urls')),
(r'^grouping/', include('grouping.urls')),
) )