Initial set of changes to support user document folders

This commit is contained in:
Roberto Rosario
2011-04-18 03:26:20 -04:00
parent f05fa53b0b
commit 1d8531248a
9 changed files with 284 additions and 0 deletions

43
apps/folders/__init__.py Normal file
View File

@@ -0,0 +1,43 @@
from django.utils.translation import ugettext_lazy as _
from navigation.api import register_links, register_menu, \
register_model_list_columns, register_multi_item_links
#from main.api import register_diagnostic
from permissions.api import register_permissions
from models import Folder
folder_list = {'text': _(u'folder list'), 'view': 'folder_list', 'famfam': 'folder'}
folder_create = {'text': _('create folder'), 'view': 'folder_create', 'famfam': 'folder_add'}
folder_edit = {'text': _('edit'), 'view': 'folder_edit', 'args': 'object.id', 'famfam': 'folder_edit'}
folder_delete = {'text': _('delete'), 'view': 'folder_delete', 'args': 'object.id', 'famfam': 'folder_delete'}
#document_create_multiple = {'text': _('upload multiple new documents'), 'view': 'document_create_multiple', 'famfam': 'page_add', 'permissions': {'namespace': 'documents', 'permissions': [PERMISSION_DOCUMENT_CREATE]}}
#document_create_sibling = {'text': _('upload new document using same metadata'), 'view': 'document_create_sibling', 'args': 'object.id', 'famfam': 'page_copy', 'permissions': {'namespace': 'documents', 'permissions': [PERMISSION_DOCUMENT_CREATE]}}
#document_view = {'text': _('details (advanced)'), 'view': 'document_view', 'args': 'object.id', 'famfam': 'page', 'permissions': {'namespace': 'documents', 'permissions': [PERMISSION_DOCUMENT_VIEW]}}
#document_view_simple = {'text': _('details (simple)'), 'view': 'document_view_simple', 'args': 'object.id', 'famfam': 'page', 'permissions': {'namespace': 'documents', 'permissions': [PERMISSION_DOCUMENT_VIEW]}}
#document_multiple_delete = {'text': _('delete'), 'view': 'document_multiple_delete', 'famfam': 'page_delete', 'permissions': {'namespace': 'documents', 'permissions': [PERMISSION_DOCUMENT_DELETE]}}
#document_edit_metadata = {'text': _('edit metadata'), 'view': 'document_edit_metadata', 'args': 'object.id', 'famfam': 'page_edit', 'permissions': {'namespace': 'documents', 'permissions': [PERMISSION_DOCUMENT_METADATA_EDIT]}}
#document_multiple_edit_metadata = {'text': _('edit metadata'), 'view': 'document_multiple_edit_metadata', 'famfam': 'page_edit', 'permissions': {'namespace': 'documents', 'permissions': [PERMISSION_DOCUMENT_METADATA_EDIT]}}
#document_preview = {'text': _('preview'), 'class': 'fancybox', 'view': 'document_preview', 'args': 'object.id', 'famfam': 'magnifier', 'permissions': {'namespace': 'documents', 'permissions': [PERMISSION_DOCUMENT_VIEW]}}
#document_download = {'text': _('download'), 'view': 'document_download', 'args': 'object.id', 'famfam': 'page_save', 'permissions': {'namespace': 'documents', 'permissions': [PERMISSION_DOCUMENT_DOWNLOAD]}}
#document_find_duplicates = {'text': _('find duplicates'), 'view': 'document_find_duplicates', 'args': 'object.id', 'famfam': 'page_refresh', 'permissions': {'namespace': 'documents', 'permissions': [PERMISSION_DOCUMENT_VIEW]}}
#document_find_all_duplicates = {'text': _('find all duplicates'), 'view': 'document_find_all_duplicates', 'famfam': 'page_refresh', 'permissions': {'namespace': 'documents', 'permissions': [PERMISSION_DOCUMENT_VIEW]}}
#document_clear_transformations = {'text': _('clear all transformations'), 'view': 'document_clear_transformations', 'args': 'object.id', 'famfam': 'page_paintbrush', 'permissions': {'namespace': 'documents', 'permissions': [PERMISSION_DOCUMENT_TRANSFORM]}}
#document_multiple_clear_transformations = {'text': _('clear all transformations'), 'view': 'document_multiple_clear_transformations', 'famfam': 'page_paintbrush', 'permissions': {'namespace': 'documents', 'permissions': [PERMISSION_DOCUMENT_TRANSFORM]}}
#register_links(Document, [document_view_simple, document_view, document_edit, document_edit_metadata, document_delete, document_download, document_find_duplicates, document_clear_transformations], menu_name='sidebar')
#register_links(Document, [document_list_recent, document_list, document_create, document_create_multiple, document_create_sibling], menu_name='sidebar')
#register_multi_item_links(['document_list'], [document_multiple_clear_transformations, document_multiple_edit_metadata, document_multiple_delete])
#####register_links(['folder_list', 'document_list_recent', 'document_list', 'document_create', 'document_create_multiple', 'upload_document_with_type', 'upload_multiple_documents_with_type'], [folder_list, folder_create], menu_name='sidebar')
register_links(Folder, [folder_edit, folder_delete])
register_links(['folder_edit', 'folder_delete', 'folder_list', 'folder_create'], [folder_list, folder_create], menu_name='sidebar')
register_menu([
{'text': _('folders'), 'view': 'folder_list', 'links': [
folder_list, folder_create
], 'famfam': 'folder', 'position': 2}])

17
apps/folders/admin.py Normal file
View File

@@ -0,0 +1,17 @@
from django.contrib import admin
from models import Folder, FolderDocument
class FolderDocumentInline(admin.StackedInline):
model = FolderDocument
extra = 1
classes = ('collapse-open',)
allow_add = True
class FolderAdmin(admin.ModelAdmin):
inlines = [FolderDocumentInline]
admin.site.register(Folder, FolderAdmin)

11
apps/folders/forms.py Normal file
View File

@@ -0,0 +1,11 @@
from django import forms
from django.utils.translation import ugettext as _
#from django.template.defaultfilters import capfirst
from models import Folder
class FolderForm(forms.ModelForm):
class Meta:
model = Folder
fields = ('title',)

43
apps/folders/models.py Normal file
View File

@@ -0,0 +1,43 @@
from datetime import datetime
from django.db import models
from django.utils.translation import ugettext as _
from django.contrib.auth.models import User
from documents.models import Document
class Folder(models.Model):
title = models.CharField(max_length=32, verbose_name=_(u'title'), db_index=True)
user = models.ForeignKey(User, verbose_name=_(u'user'))
datetime_created = models.DateTimeField(verbose_name=_(u'datetime created'))
def __unicode__(self):
return self.title
def save(self, *args, **kwargs):
if not self.pk:
self.datetime_created = datetime.now()
super(Folder, self).save(*args, **kwargs)
@models.permalink
def get_absolute_url(self):
return ('folder_view', [self.pk])
class Meta:
unique_together = ('title', 'user')
ordering = ('title',)
verbose_name = _(u'folder')
verbose_name_plural = _(u'folders')
class FolderDocument(models.Model):
folder = models.ForeignKey(Folder, verbose_name=_('folder'))
document = models.ForeignKey(Document, verbose_name=_('document'))
def __unicode__(self):
return unicode(self.document)
class Meta:
verbose_name = _(u'folder document')
verbose_name_plural = _(u'folders documents')

23
apps/folders/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
"""}

10
apps/folders/urls.py Normal file
View File

@@ -0,0 +1,10 @@
from django.conf.urls.defaults import patterns, url
urlpatterns = patterns('folders.views',
url(r'^list/$', 'folder_list', (), 'folder_list'),
url(r'^create/$', 'folder_create', (), 'folder_create'),
url(r'^(?P<folder_id>\d+)/edit/$', 'folder_edit', (), 'folder_edit'),
url(r'^(?P<folder_id>\d+)/delete/$', 'folder_delete', (), 'folder_delete'),
url(r'^(?P<folder_id>\d+)/$', 'folder_view', (), 'folder_view'),
)

135
apps/folders/views.py Normal file
View File

@@ -0,0 +1,135 @@
from django.utils.translation import ugettext as _
from django.http import HttpResponse, HttpResponseRedirect
from django.shortcuts import render_to_response, get_object_or_404
from django.template import RequestContext
from django.contrib import messages
from django.views.generic.list_detail import object_detail, object_list
from django.core.urlresolvers import reverse
from django.views.generic.create_update import create_object, delete_object, update_object
from documents import PERMISSION_DOCUMENT_VIEW
from documents.models import Document
from permissions.api import check_permissions
from models import Folder, FolderDocument
from forms import FolderForm
def folder_list(request):
return object_list(
request,
queryset=Folder.objects.filter(user=request.user),
template_name='generic_list.html',
extra_context={
'title': _(u'folders'),
'multi_select_as_buttons': True,
'extra_columns': [
{'name': _(u'created'), 'attribute': 'datetime_created'},
{'name': _(u'documents'), 'attribute': lambda x: x.folderdocument_set.count()}
]
},
)
def folder_create(request):
if request.method == 'POST':
form = FolderForm(request.POST)
if form.is_valid():
folder, created = Folder.objects.get_or_create(user=request.user, title=form.cleaned_data['title'])
if created:
messages.success(request, _(u'Folder created successfully'))
return HttpResponseRedirect(reverse('folder_list'))
else:
messages.error(request, _(u'A folder named: %s, already exists.') % form.cleaned_data['title'])
else:
form = FolderForm()
return render_to_response('generic_form.html', {
'title': _(u'create folder'),
'form': form,
},
context_instance=RequestContext(request))
def folder_edit(request, folder_id):
folder = get_object_or_404(Folder, pk=folder_id)
if request.method == 'POST':
form = FolderForm(request.POST)
if form.is_valid():
folder.title=form.cleaned_data['title']
try:
folder.save()
messages.success(request, _(u'Folder edited successfully'))
return HttpResponseRedirect(reverse('folder_list'))
except Exception, e:
messages.error(request, _(u'Error editing folder; %s') % e)
else:
form = FolderForm(instance=folder)
return render_to_response('generic_form.html', {
'title': _(u'edit folder: %s') % folder,
'form': form,
'object': folder,
},
context_instance=RequestContext(request))
def folder_delete(request, folder_id):
folder = get_object_or_404(Folder, pk=folder_id)
post_action_redirect = reverse('folder_list')
previous = request.POST.get('previous', request.GET.get('previous', request.META.get('HTTP_REFERER', '/')))
next = request.POST.get('next', request.GET.get('next', post_action_redirect if post_action_redirect else request.META.get('HTTP_REFERER', '/')))
if request.method == 'POST':
try:
folder.delete()
messages.success(request, _(u'Folder: %s deleted successfully.') % folder)
except Exception, e:
messages.error(request, _(u'Folder: %(folder)s delete error: %(error)s') % {
'folder': folder, 'error': e})
return HttpResponseRedirect(next)
context = {
'object_name': _(u'folder'),
'delete_view': True,
'previous': previous,
'next': next,
'object': folder,
'title': _(u'Are you sure you with to delete the folder: %s?') % folder
}
return render_to_response('generic_confirm.html', context,
context_instance=RequestContext(request))
def folder_view(request, folder_id):
folder = get_object_or_404(Folder, pk=folder_id)
return render_to_response('generic_list.html', {
'object_list': [folder_document.document for folder_document in folder.folderdocument_set.all()],
'title': _(u'documents in folder: %s') % folder,
'multi_select_as_buttons': True,
}, context_instance=RequestContext(request))
def folder_add_document(request, folder_id, document_id):
folder = get_object_or_404(Folder, pk=folder_id)
document = get_object_or_404(Document, pk=document_id)
check_permissions(request.user, 'documents', [PERMISSION_DOCUMENT_VIEW])
if request.method == 'POST':
previous = request.META.get('HTTP_REFERER', '/')
folder_document, created = FolderDocument.objects.get_or_create(folder=folder, document=document)
if created:
messages.success(request, _(u'Document: %(document)s added to folder: %(folder)s successfully.') % {
'document': document, 'folder': folder})
else:
messages.warning(request, _(u'Document: %(document)s is already in folder: %(folder)s.') % {
'document': document, 'folder': folder})
return HttpResponseRedirect(previous)

View File

@@ -138,6 +138,7 @@ INSTALLED_APPS = (
'sentry.client.celery',
'filesystem_serving',
'storage',
'folders',
)
TEMPLATE_CONTEXT_PROCESSORS = (

View File

@@ -10,6 +10,7 @@ urlpatterns = patterns('',
(r'^', include('common.urls')),
(r'^', include('main.urls')),
(r'^documents/', include('documents.urls')),
(r'^folders/', include('folders.urls')),
(r'^filesystem_serving/', include('filesystem_serving.urls')),
(r'^search/', include('dynamic_search.urls')),
(r'^ocr/', include('ocr.urls')),