From 2816c1f86f52e2115854a9e41d81efd04d9a2b44 Mon Sep 17 00:00:00 2001 From: Roberto Rosario Date: Wed, 6 Jul 2011 01:31:27 -0400 Subject: [PATCH] Got upload view working, staging preview and delete working ok --- apps/documents/__init__.py | 17 +- apps/documents/conf/settings.py | 14 +- apps/documents/forms.py | 4 +- apps/documents/literals.py | 4 - apps/documents/urls.py | 11 +- apps/documents/views.py | 19 +- apps/documents/wizards.py | 8 +- .../templatetags/navigation_tags.py | 14 + apps/sources/__init__.py | 19 + apps/sources/admin.py | 2 - apps/sources/forms.py | 39 ++ apps/sources/models.py | 18 +- apps/{documents => sources}/staging.py | 43 +- apps/sources/urls.py | 23 ++ apps/sources/views.py | 369 +++++++++++++++++- urls.py | 1 + 16 files changed, 520 insertions(+), 85 deletions(-) create mode 100644 apps/sources/forms.py rename apps/{documents => sources}/staging.py (73%) create mode 100644 apps/sources/urls.py diff --git a/apps/documents/__init__.py b/apps/documents/__init__.py index ace7578129..24ef2a7c59 100644 --- a/apps/documents/__init__.py +++ b/apps/documents/__init__.py @@ -13,9 +13,6 @@ from metadata.api import get_metadata_string from documents.models import Document, DocumentPage, \ DocumentPageTransformation, DocumentType, DocumentTypeFilename -from documents.staging import StagingFile -from documents.conf.settings import USE_STAGING_DIRECTORY -from documents.conf.settings import PER_USER_STAGING_DIRECTORY from documents.literals import PERMISSION_DOCUMENT_CREATE, \ PERMISSION_DOCUMENT_PROPERTIES_EDIT, PERMISSION_DOCUMENT_VIEW, \ PERMISSION_DOCUMENT_DELETE, PERMISSION_DOCUMENT_DOWNLOAD, \ @@ -107,13 +104,6 @@ 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': [PERMISSION_DOCUMENT_VIEW]} -upload_document_from_local = {'text': _(u'local'), 'view': 'upload_document_from_local', 'famfam': 'drive_disk', 'keep_query': True} -upload_document_from_staging = {'text': _(u'staging'), 'view': 'upload_document_from_staging', 'famfam': 'drive_network', 'keep_query': True, 'condition': lambda x: USE_STAGING_DIRECTORY} -upload_document_from_user_staging = {'text': _(u'user staging'), 'view': 'upload_document_from_user_staging', 'famfam': 'drive_user', 'keep_query': True, 'condition': lambda x: PER_USER_STAGING_DIRECTORY} - -staging_file_preview = {'text': _(u'preview'), 'class': 'fancybox-noscaling', 'view': 'staging_file_preview', 'args': ['source', 'object.id'], 'famfam': 'drive_magnify'} -staging_file_delete = {'text': _(u'delete'), 'view': 'staging_file_delete', 'args': ['source', 'object.id'], 'famfam': 'drive_delete'} - # Document type related links document_type_list = {'text': _(u'document type list'), 'view': 'document_type_list', 'famfam': 'layout', 'permissions': [PERMISSION_DOCUMENT_VIEW]} document_type_document_list = {'text': _(u'documents of this type'), 'view': 'document_type_document_list', 'args': 'object.id', 'famfam': 'page_go', 'permissions': [PERMISSION_DOCUMENT_VIEW]} @@ -141,7 +131,7 @@ register_links(['document_type_filename_edit', 'document_type_filename_delete'], register_links(Document, [document_edit, document_print, document_delete, document_download, document_find_duplicates, document_clear_transformations, document_create_siblings]) register_multi_item_links(['folder_view', 'index_instance_list', 'document_type_document_list', 'search', 'results', 'document_group_view', 'document_list', 'document_list_recent'], [document_multiple_clear_transformations, document_multiple_delete]) -register_links(['document_list_recent', 'document_list', 'document_create', 'document_create_multiple', 'upload_document', 'upload_document_from_local', 'upload_document_from_staging', 'upload_document_from_user_staging', 'document_find_duplicates'], [document_list_recent, document_list, document_create_multiple], menu_name='secondary_menu') +register_links(['document_list_recent', 'document_list', 'document_create', 'document_create_multiple', 'upload_interactive', 'document_find_duplicates'], [document_list_recent, document_list, document_create_multiple], menu_name='secondary_menu') # Document page links register_links(DocumentPage, [ @@ -157,17 +147,12 @@ register_links(DocumentPage, [ register_links(['document_page_view'], [document_page_rotate_left, document_page_rotate_right, document_page_zoom_in, document_page_zoom_out], menu_name='form_header') -# Upload sources -register_links(['upload_document_from_local', 'upload_document_from_staging', 'upload_document_from_user_staging'], [upload_document_from_local, upload_document_from_staging, upload_document_from_user_staging], menu_name='form_header') - register_links(DocumentPageTransformation, [document_page_transformation_edit, document_page_transformation_delete]) register_links(DocumentPageTransformation, [document_page_transformation_page_edit, document_page_transformation_page_view], menu_name='sidebar') register_links('document_page_transformation_list', [document_page_transformation_create], menu_name='sidebar') register_links('document_page_transformation_create', [document_page_transformation_create], menu_name='sidebar') register_links(['document_page_transformation_edit', 'document_page_transformation_delete'], [document_page_transformation_page_transformation_list], menu_name='sidebar') -register_links(StagingFile, [staging_file_preview, staging_file_delete]) - register_diagnostic('documents', _(u'Documents'), document_missing_list) register_tool(document_find_all_duplicates, namespace='documents', title=_(u'documents')) diff --git a/apps/documents/conf/settings.py b/apps/documents/conf/settings.py index 49af295531..a8036b44ea 100644 --- a/apps/documents/conf/settings.py +++ b/apps/documents/conf/settings.py @@ -27,13 +27,13 @@ register_settings( module=u'documents.conf.settings', settings=[ # Upload - {'name': u'USE_STAGING_DIRECTORY', 'global_name': u'DOCUMENTS_USE_STAGING_DIRECTORY', 'default': False}, - {'name': u'STAGING_DIRECTORY', 'global_name': u'DOCUMENTS_STAGING_DIRECTORY', 'default': u'/tmp/mayan/staging', 'exists': True}, - {'name': u'PER_USER_STAGING_DIRECTORY', 'global_name': u'DOCUMENTS_PER_USER_STAGING_DIRECTORY', 'default': False}, - {'name': u'USER_STAGING_DIRECTORY_ROOT', 'global_name': u'DOCUMENTS_USER_STAGING_DIRECTORY_ROOT', 'default': u'/tmp/mayan/staging/users', 'exists': True}, - {'name': u'USER_STAGING_DIRECTORY_EXPRESSION', 'global_name': u'DOCUMENTS_USER_STAGING_DIRECTORY_EXPRESSION', 'default': u'user.username'}, - {'name': u'DELETE_STAGING_FILE_AFTER_UPLOAD', 'global_name': u'DOCUMENTS_DELETE_STAGING_FILE_AFTER_UPLOAD', 'default': False}, - {'name': u'STAGING_FILES_PREVIEW_SIZE', 'global_name': u'DOCUMENTS_STAGING_FILES_PREVIEW_SIZE', 'default': u'640x480'}, + #{'name': u'USE_STAGING_DIRECTORY', 'global_name': u'DOCUMENTS_USE_STAGING_DIRECTORY', 'default': False}, + #{'name': u'STAGING_DIRECTORY', 'global_name': u'DOCUMENTS_STAGING_DIRECTORY', 'default': u'/tmp/mayan/staging', 'exists': True}, + #{'name': u'PER_USER_STAGING_DIRECTORY', 'global_name': u'DOCUMENTS_PER_USER_STAGING_DIRECTORY', 'default': False}, + #{'name': u'USER_STAGING_DIRECTORY_ROOT', 'global_name': u'DOCUMENTS_USER_STAGING_DIRECTORY_ROOT', 'default': u'/tmp/mayan/staging/users', 'exists': True}, + #{'name': u'USER_STAGING_DIRECTORY_EXPRESSION', 'global_name': u'DOCUMENTS_USER_STAGING_DIRECTORY_EXPRESSION', 'default': u'user.username'}, + #{'name': u'DELETE_STAGING_FILE_AFTER_UPLOAD', 'global_name': u'DOCUMENTS_DELETE_STAGING_FILE_AFTER_UPLOAD', 'default': False}, + #{'name': u'STAGING_FILES_PREVIEW_SIZE', 'global_name': u'DOCUMENTS_STAGING_FILES_PREVIEW_SIZE', 'default': u'640x480'}, # Saving {'name': u'CHECKSUM_FUNCTION', 'global_name': u'DOCUMENTS_CHECKSUM_FUNCTION', 'default': default_checksum}, {'name': u'UUID_FUNCTION', 'global_name': u'DOCUMENTS_UUID_FUNCTION', 'default': default_uuid}, diff --git a/apps/documents/forms.py b/apps/documents/forms.py index 9553b2ce00..bfd4eb0d21 100644 --- a/apps/documents/forms.py +++ b/apps/documents/forms.py @@ -265,7 +265,7 @@ class PrintForm(forms.Form): page_orientation = forms.ChoiceField(choices=PAGE_ORIENTATION_CHOICES, initial=DEFAULT_PAGE_ORIENTATION, label=_(u'Page orientation'), required=True) page_range = forms.CharField(label=_(u'Page range'), required=False) - +''' class StagingDocumentForm(DocumentForm): """ Form that show all the files in the staging folder specified by the @@ -290,7 +290,7 @@ class StagingDocumentForm(DocumentForm): class Meta(DocumentForm.Meta): exclude = ('description', 'file', 'document_type', 'tags') - +''' class DocumentTypeForm(forms.ModelForm): """ diff --git a/apps/documents/literals.py b/apps/documents/literals.py index aff31396f3..b2c0f023c2 100644 --- a/apps/documents/literals.py +++ b/apps/documents/literals.py @@ -18,10 +18,6 @@ PERMISSION_DOCUMENT_TYPE_EDIT = {'namespace': 'documents', 'name': 'document_typ PERMISSION_DOCUMENT_TYPE_DELETE = {'namespace': 'documents', 'name': 'document_type_delete', 'label': _(u'Delete document types')} PERMISSION_DOCUMENT_TYPE_CREATE = {'namespace': 'documents', 'name': 'document_type_create', 'label': _(u'Create document types')} -UPLOAD_SOURCE_LOCAL = u'local' -UPLOAD_SOURCE_STAGING = u'staging' -UPLOAD_SOURCE_USER_STAGING = u'user_staging' - HISTORY_DOCUMENT_CREATED = { 'namespace': 'documents', 'name': 'document_created', 'label': _(u'Document creation'), diff --git a/apps/documents/urls.py b/apps/documents/urls.py index 1add9cd55b..4dc99f37de 100644 --- a/apps/documents/urls.py +++ b/apps/documents/urls.py @@ -7,18 +7,14 @@ from documents.conf.settings import PRINT_SIZE from documents.conf.settings import THUMBNAIL_SIZE from documents.conf.settings import DISPLAY_SIZE from documents.conf.settings import MULTIPAGE_PREVIEW_SIZE -from documents.literals import UPLOAD_SOURCE_LOCAL, \ - UPLOAD_SOURCE_STAGING, UPLOAD_SOURCE_USER_STAGING +#from documents.literals import UPLOAD_SOURCE_LOCAL, \ +# UPLOAD_SOURCE_STAGING, UPLOAD_SOURCE_USER_STAGING urlpatterns = patterns('documents.views', url(r'^list/$', 'document_list', (), 'document_list'), url(r'^list/recent/$', 'document_list_recent', (), 'document_list_recent'), url(r'^create/from/local/multiple/$', 'document_create', (), 'document_create_multiple'), - url(r'^upload/local/$', 'upload_document_with_type', {'source': UPLOAD_SOURCE_LOCAL}, 'upload_document_from_local'), - url(r'^upload/staging/$', 'upload_document_with_type', {'source': UPLOAD_SOURCE_STAGING}, 'upload_document_from_staging'), - url(r'^upload/staging/user/$', 'upload_document_with_type', {'source': UPLOAD_SOURCE_USER_STAGING}, 'upload_document_from_user_staging'), - url(r'^(?P\d+)/view/$', 'document_view', (), 'document_view_simple'), url(r'^(?P\d+)/view/advanced/$', 'document_view', {'advanced': True}, 'document_view_advanced'), url(r'^(?P\d+)/delete/$', 'document_delete', (), 'document_delete'), @@ -41,9 +37,6 @@ urlpatterns = patterns('documents.views', url(r'^multiple/clear_transformations/$', 'document_multiple_clear_transformations', (), 'document_multiple_clear_transformations'), url(r'^duplicates/list/$', 'document_find_all_duplicates', (), 'document_find_all_duplicates'), - url(r'^staging_file/type/(?P\w+)/(?P\w+)/preview/$', 'staging_file_preview', (), 'staging_file_preview'), - url(r'^staging_file/type/(?P\w+)/(?P\w+)/delete/$', 'staging_file_delete', (), 'staging_file_delete'), - url(r'^page/(?P\d+)/$', 'document_page_view', (), 'document_page_view'), url(r'^page/(?P\d+)/text/$', 'document_page_text', (), 'document_page_text'), url(r'^page/(?P\d+)/edit/$', 'document_page_edit', (), 'document_page_edit'), diff --git a/apps/documents/views.py b/apps/documents/views.py index d29e9eda18..594009b1b2 100644 --- a/apps/documents/views.py +++ b/apps/documents/views.py @@ -36,10 +36,6 @@ from permissions.api import check_permissions from document_indexing.api import update_indexes, delete_indexes from history.api import create_history -from documents.conf.settings import DELETE_STAGING_FILE_AFTER_UPLOAD -from documents.conf.settings import USE_STAGING_DIRECTORY -from documents.conf.settings import PER_USER_STAGING_DIRECTORY - from documents.conf.settings import PREVIEW_SIZE from documents.conf.settings import THUMBNAIL_SIZE from documents.conf.settings import STORAGE_BACKEND @@ -61,7 +57,7 @@ from documents.literals import HISTORY_DOCUMENT_CREATED, \ from documents.forms import DocumentTypeSelectForm, \ DocumentForm, DocumentForm_edit, DocumentPropertiesForm, \ - StagingDocumentForm, DocumentPreviewForm, \ + DocumentPreviewForm, \ DocumentPageForm, DocumentPageTransformationForm, \ DocumentContentForm, DocumentPageForm_edit, \ DocumentPageForm_text, PrintForm, DocumentTypeForm, \ @@ -69,11 +65,8 @@ from documents.forms import DocumentTypeSelectForm, \ from documents.wizards import DocumentCreateWizard from documents.models import Document, DocumentType, DocumentPage, \ DocumentPageTransformation, RecentDocument, DocumentTypeFilename -from documents.staging import create_staging_file_class from documents.literals import PICTURE_ERROR_SMALL, PICTURE_ERROR_MEDIUM, \ PICTURE_UNKNOWN_SMALL, PICTURE_UNKNOWN_MEDIUM -from documents.literals import UPLOAD_SOURCE_LOCAL, \ - UPLOAD_SOURCE_STAGING, UPLOAD_SOURCE_USER_STAGING # Document type permissions from documents.literals import PERMISSION_DOCUMENT_TYPE_EDIT, \ @@ -116,10 +109,10 @@ def document_create_siblings(request, document_id): if document.document_type_id: query_dict['document_type_id'] = document.document_type_id - url = reverse('upload_document_from_local') + url = reverse('upload_interactive') return HttpResponseRedirect('%s?%s' % (url, urlencode(query_dict))) - +''' def _handle_save_document(request, document, form=None): RecentDocument.objects.add_document_for_user(request.user, document) @@ -279,7 +272,7 @@ def upload_document_with_type(request, source): } return render_to_response('generic_form.html', context, context_instance=RequestContext(request)) - +''' def document_view(request, document_id, advanced=False): check_permissions(request.user, [PERMISSION_DOCUMENT_VIEW]) @@ -545,7 +538,7 @@ def document_download(request, document_id): messages.error(request, e) return HttpResponseRedirect(request.META['HTTP_REFERER']) - +''' def staging_file_preview(request, source, staging_file_id): check_permissions(request.user, [PERMISSION_DOCUMENT_CREATE]) StagingFile = create_staging_file_class(request, source) @@ -596,7 +589,7 @@ def staging_file_delete(request, source, staging_file_id): 'previous': previous, 'form_icon': u'drive_delete.png', }, context_instance=RequestContext(request)) - +''' def document_page_transformation_list(request, document_page_id): check_permissions(request.user, [PERMISSION_DOCUMENT_TRANSFORM]) diff --git a/apps/documents/wizards.py b/apps/documents/wizards.py index c2b76b9028..a61ba4960a 100644 --- a/apps/documents/wizards.py +++ b/apps/documents/wizards.py @@ -30,7 +30,6 @@ class DocumentCreateWizard(BoundFormWizard): def __init__(self, *args, **kwargs): self.query_dict = {} - self.multiple = kwargs.pop('multiple', True) self.step_titles = kwargs.pop('step_titles', [ _(u'step 1 of 3: Document type'), _(u'step 2 of 3: Metadata selection'), @@ -75,13 +74,8 @@ class DocumentCreateWizard(BoundFormWizard): return 'generic_wizard.html' def done(self, request, form_list): - if self.multiple: - view = 'upload_document_from_local' - else: - view = 'upload_document' - if self.document_type: self.query_dict['document_type_id'] = self.document_type.pk - url = urlquote(reverse(view), self.query_dict) + url = urlquote(reverse('upload_interactive'), self.query_dict) return HttpResponseRedirect(url) diff --git a/apps/navigation/templatetags/navigation_tags.py b/apps/navigation/templatetags/navigation_tags.py index b54ab6ddfc..f849f040f7 100644 --- a/apps/navigation/templatetags/navigation_tags.py +++ b/apps/navigation/templatetags/navigation_tags.py @@ -131,6 +131,9 @@ def _get_object_navigation_links(context, menu_name=None, links_dict=object_navi current_view = resolve_to_name(current_path) context_links = [] + # Don't fudge with the original global dictionary + links_dict = links_dict.copy() + query_string = urlparse.urlparse(request.get_full_path()).query or urlparse.urlparse(request.META.get('HTTP_REFERER', u'/')).query parsed_query_string = urlparse.parse_qs(query_string) @@ -155,6 +158,16 @@ def _get_object_navigation_links(context, menu_name=None, links_dict=object_navi except VariableDoesNotExist: obj = None + try: + """ + Check for and inject a temporary navigation dictionary + """ + temp_navigation_links = Variable('temporary_navigation_links').resolve(context) + if temp_navigation_links: + links_dict.update(temp_navigation_links) + except VariableDoesNotExist: + pass + try: links = links_dict[menu_name][current_view]['links'] for link in resolve_links(context, links, current_view, current_path, parsed_query_string): @@ -169,6 +182,7 @@ def _get_object_navigation_links(context, menu_name=None, links_dict=object_navi except KeyError: pass + return context_links diff --git a/apps/sources/__init__.py b/apps/sources/__init__.py index e69de29bb2..aa31d60f1d 100644 --- a/apps/sources/__init__.py +++ b/apps/sources/__init__.py @@ -0,0 +1,19 @@ +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_top_menu, \ + register_model_list_columns, register_multi_item_links, \ + register_sidebar_template + +from sources.staging import StagingFile + +upload_document_from_local = {'text': _(u'local'), 'view': 'upload_document_from_local', 'famfam': 'drive_disk', 'keep_query': True} +upload_document_from_staging = {'text': _(u'staging'), 'view': 'upload_document_from_staging', 'famfam': 'drive_network', 'keep_query': True}#, 'condition': lambda x: USE_STAGING_DIRECTORY} +upload_document_from_user_staging = {'text': _(u'user staging'), 'view': 'upload_document_from_user_staging', 'famfam': 'drive_user', 'keep_query': True}#, 'condition': lambda x: PER_USER_STAGING_DIRECTORY} + +staging_file_preview = {'text': _(u'preview'), 'class': 'fancybox-noscaling', 'view': 'staging_file_preview', 'args': ['source.source_type', 'source.pk', 'object.id'], 'famfam': 'zoom'} +staging_file_delete = {'text': _(u'delete'), 'view': 'staging_file_delete', 'args': ['source.source_type', 'source.pk', 'object.id'], 'famfam': 'delete'} + +register_links(StagingFile, [staging_file_preview, staging_file_delete]) + diff --git a/apps/sources/admin.py b/apps/sources/admin.py index 716d8224e5..3cbf7078fb 100644 --- a/apps/sources/admin.py +++ b/apps/sources/admin.py @@ -2,7 +2,5 @@ from django.contrib import admin from sources.models import StagingFolder, WebForm - - admin.site.register(StagingFolder) admin.site.register(WebForm) diff --git a/apps/sources/forms.py b/apps/sources/forms.py new file mode 100644 index 0000000000..48f2a379c3 --- /dev/null +++ b/apps/sources/forms.py @@ -0,0 +1,39 @@ +from django import forms +from django.utils.translation import ugettext_lazy as _ +from django.utils.translation import ugettext +from django.core.urlresolvers import reverse +from django.utils.safestring import mark_safe +from django.conf import settings + +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 documents.forms import DocumentForm + + +class StagingDocumentForm(DocumentForm): + """ + Form that show all the files in the staging folder specified by the + StagingFile class passed as 'cls' argument + """ + def __init__(self, *args, **kwargs): + cls = kwargs.pop('cls') + super(StagingDocumentForm, self).__init__(*args, **kwargs) + try: + self.fields['staging_file_id'].choices = [ + (staging_file.id, staging_file) for staging_file in cls.get_all() + ] + except: + pass + + # Put staging_list field first in the field order list + staging_list_index = self.fields.keyOrder.index('staging_file_id') + staging_list = self.fields.keyOrder.pop(staging_list_index) + self.fields.keyOrder.insert(0, staging_list) + + staging_file_id = forms.ChoiceField(label=_(u'Staging file')) + + class Meta(DocumentForm.Meta): + exclude = ('description', 'file', 'document_type', 'tags') diff --git a/apps/sources/models.py b/apps/sources/models.py index ae4cf1e9c7..8dd162e8a1 100644 --- a/apps/sources/models.py +++ b/apps/sources/models.py @@ -40,8 +40,8 @@ SOURCE_ICON_CHOICES = ( (SOURCE_ICON_WORLD, _(u'world')) ) -SOURCE_CHOICE_WEB_FORM = 'wform' -SOURCE_CHOICE_STAGING = 'stagn' +SOURCE_CHOICE_WEB_FORM = 'webform' +SOURCE_CHOICE_STAGING = 'staging' SOURCE_CHOICES = ( (SOURCE_CHOICE_WEB_FORM, _(u'Web form')), @@ -56,15 +56,11 @@ class BaseModel(models.Model): blacklist = models.TextField(blank=True, verbose_name=_(u'blacklist')) document_type = models.ForeignKey(DocumentType, blank=True, null=True, verbose_name=_(u'document type')) - # M2M - # Default Metadata sets - # Default Metadata types & default values - def __unicode__(self): return u'%s (%s)' % (self.title, dict(SOURCE_CHOICES).get(self.source_type)) class Meta: - ordering = ['title'] + ordering = ('title',) abstract = True @@ -104,6 +100,14 @@ class StagingFolder(InteractiveBaseModel): uncompress = models.CharField(max_length=1, choices=SOURCE_INTERACTIVE_UNCOMPRESS_CHOICES, verbose_name=_(u'uncompress')) delete_after_upload = models.BooleanField(default=True, verbose_name=_(u'delete after upload')) + def get_preview_size(self): + dimensions = [] + dimensions.append(unicode(self.preview_width)) + if self.preview_height: + dimensions.append(unicode(self.preview_height)) + + return u'x'.join(dimensions) + class Meta: verbose_name = _(u'staging folder') verbose_name_plural = _(u'staging folder') diff --git a/apps/documents/staging.py b/apps/sources/staging.py similarity index 73% rename from apps/documents/staging.py rename to apps/sources/staging.py index ca11ddc20f..2dccf9d40a 100644 --- a/apps/documents/staging.py +++ b/apps/sources/staging.py @@ -11,24 +11,30 @@ from django.utils.translation import ugettext_lazy as _ from converter import TRANFORMATION_CHOICES from converter.api import convert, cache_cleanup -from documents.conf.settings import STAGING_DIRECTORY -from documents.conf.settings import DEFAULT_TRANSFORMATIONS -from documents.conf.settings import STAGING_FILES_PREVIEW_SIZE -from documents.conf.settings import USER_STAGING_DIRECTORY_ROOT -from documents.conf.settings import USER_STAGING_DIRECTORY_EXPRESSION +#from documents.conf.settings import STAGING_DIRECTORY +STAGING_DIRECTORY = u'/tmp' +#from documents.conf.settings import DEFAULT_TRANSFORMATIONS +#from documents.conf.settings import STAGING_FILES_PREVIEW_SIZE +STAGING_FILES_PREVIEW_SIZE = u'640' +#from documents.conf.settings import USER_STAGING_DIRECTORY_ROOT +#from documents.conf.settings import USER_STAGING_DIRECTORY_EXPRESSION -from documents.literals import UPLOAD_SOURCE_STAGING, \ - UPLOAD_SOURCE_USER_STAGING +#from documents.literals import UPLOAD_SOURCE_STAGING, \ +# UPLOAD_SOURCE_USER_STAGING + +UPLOAD_SOURCE_LOCAL = u'local' +UPLOAD_SOURCE_STAGING = u'staging' +UPLOAD_SOURCE_USER_STAGING = u'user_staging' HASH_FUNCTION = lambda x: hashlib.sha256(x).hexdigest() #TODO: Do benchmarks #func = lambda:[StagingFile.get_all() is None for i in range(100)] #t1=time.time();func();t2=time.time();print '%s took %0.3f ms' % (func.func_name, (t2-t1)*1000.0) -STAGING_FILE_FUNCTIONS = { - UPLOAD_SOURCE_STAGING: lambda x: STAGING_DIRECTORY, - UPLOAD_SOURCE_USER_STAGING: lambda x: os.path.join(USER_STAGING_DIRECTORY_ROOT, eval(USER_STAGING_DIRECTORY_EXPRESSION, {'user': x.user})) -} +#STAGING_FILE_FUNCTIONS = { +# UPLOAD_SOURCE_STAGING: lambda x: STAGING_DIRECTORY, +# UPLOAD_SOURCE_USER_STAGING: lambda x: os.path.join(USER_STAGING_DIRECTORY_ROOT, eval(USER_STAGING_DIRECTORY_EXPRESSION, {'user': x.user})) +#} def evaluate_user_staging_path(request, source): @@ -52,7 +58,8 @@ def _return_new_class(): def create_staging_file_class(request, source): cls = _return_new_class() - cls.set_path(evaluate_user_staging_path(request, source)) + #cls.set_path(evaluate_user_staging_path(request, source)) + cls.set_path(source) return cls @@ -120,8 +127,8 @@ class StagingFile(object): raise Exception(ugettext(u'Unable to upload staging file: %s') % exc) def delete(self): - tranformation_string, errors = get_transformation_string(DEFAULT_TRANSFORMATIONS) - cache_cleanup(self.filepath, size=STAGING_FILES_PREVIEW_SIZE, extra_options=tranformation_string) + #tranformation_string, errors = get_transformation_string(DEFAULT_TRANSFORMATIONS) + cache_cleanup(self.filepath, size=STAGING_FILES_PREVIEW_SIZE)#, extra_options=tranformation_string) try: os.unlink(self.filepath) except OSError, exc: @@ -130,9 +137,11 @@ class StagingFile(object): else: raise OSError(ugettext(u'Unable to delete staging file: %s') % exc) - def preview(self): - tranformation_string, errors = get_transformation_string(DEFAULT_TRANSFORMATIONS) - output_file = convert(self.filepath, size=STAGING_FILES_PREVIEW_SIZE, extra_options=tranformation_string, cleanup_files=False) + def preview(self, preview_size): + errors = [] + #tranformation_string, errors = get_transformation_string(DEFAULT_TRANSFORMATIONS) + #output_file = convert(self.filepath, size=STAGING_FILES_PREVIEW_SIZE, extra_options=tranformation_string, cleanup_files=False) + output_file = convert(self.filepath, size=preview_size, cleanup_files=False) return output_file, errors diff --git a/apps/sources/urls.py b/apps/sources/urls.py new file mode 100644 index 0000000000..380d462d0e --- /dev/null +++ b/apps/sources/urls.py @@ -0,0 +1,23 @@ +from django.conf.urls.defaults import patterns, url + +#from converter.api import QUALITY_HIGH, QUALITY_PRINT + +#from documents.conf.settings import PREVIEW_SIZE +#from documents.conf.settings import PRINT_SIZE +#from documents.conf.settings import THUMBNAIL_SIZE +#from documents.conf.settings import DISPLAY_SIZE +#from documents.conf.settings import MULTIPAGE_PREVIEW_SIZE +#from documents.literals import UPLOAD_SOURCE_LOCAL, \ +# UPLOAD_SOURCE_STAGING, UPLOAD_SOURCE_USER_STAGING + +urlpatterns = patterns('sources.views', + #url(r'^upload/local/$', 'upload_document_with_type', {'source': UPLOAD_SOURCE_LOCAL}, 'upload_document_from_local'), + #url(r'^upload/staging/$', 'upload_document_with_type', {'source': UPLOAD_SOURCE_STAGING}, 'upload_document_from_staging'), + #url(r'^upload/staging/user/$', 'upload_document_with_type', {'source': UPLOAD_SOURCE_USER_STAGING}, 'upload_document_from_user_staging'), + + url(r'^staging_file/type/(?P\w+)/(?P\d+)/(?P\w+)/preview/$', 'staging_file_preview', (), 'staging_file_preview'), + url(r'^staging_file/type/(?P\w+)/(?P\d+)/(?P\w+)/delete/$', 'staging_file_delete', (), 'staging_file_delete'), + + url(r'^upload/interactive/(?P\w+)/(?P\d+)/$', 'upload_interactive', (), 'upload_interactive'), + url(r'^upload/interactive/$', 'upload_interactive', (), 'upload_interactive'), +) diff --git a/apps/sources/views.py b/apps/sources/views.py index 60f00ef0ef..b23cd8dfff 100644 --- a/apps/sources/views.py +++ b/apps/sources/views.py @@ -1 +1,368 @@ -# Create your views here. +import os + +from django.http import HttpResponseRedirect +from django.shortcuts import render_to_response, get_object_or_404 +from django.template import RequestContext +from django.contrib import messages +from django.core.urlresolvers import reverse +from django.utils.translation import ugettext_lazy as _ +from django.conf import settings + +from permissions.api import check_permissions +from documents.literals import PERMISSION_DOCUMENT_CREATE +from documents.models import DocumentType +from metadata.api import save_metadata_list, \ + decode_metadata_from_url, metadata_repr_as_list +from metadata.forms import MetadataFormSet, MetadataSelectionForm +import sendfile +from converter.exceptions import UnkownConvertError, UnknownFormat +from documents.literals import PICTURE_ERROR_SMALL, PICTURE_ERROR_MEDIUM, \ + PICTURE_UNKNOWN_SMALL, PICTURE_UNKNOWN_MEDIUM + +#TEMP +from documents.forms import DocumentForm + +from sources.models import WebForm, StagingFolder +from sources.models import SOURCE_CHOICE_WEB_FORM, SOURCE_CHOICE_STAGING +from sources.staging import create_staging_file_class +from sources.forms import StagingDocumentForm + + +def upload_interactive(request, source_type=None, source_id=None): + check_permissions(request.user, [PERMISSION_DOCUMENT_CREATE]) + + subtemplates_list = [] + + tab_links = [] + + context = {} + + web_forms = WebForm.objects.filter(enabled=True) + for web_form in web_forms: + tab_links.append({ + 'text': web_form.title, + 'view': 'upload_interactive', + 'args': [u'"%s"' % web_form.source_type, web_form.pk], + 'famfam': web_form.icon, + 'keep_query': True + }) + + staging_folders = StagingFolder.objects.filter(enabled=True) + for staging_folder in staging_folders: + tab_links.append({ + 'text': staging_folder.title, + 'view': 'upload_interactive', + 'args': [u'"%s"' % staging_folder.source_type, staging_folder.pk], + 'famfam': staging_folder.icon, + 'keep_query': True + }) + + if web_forms.count() == 0 and staging_folders.count() == 0: + subtemplates_list.append( + { + 'name': 'generic_subtemplate.html', + 'context': { + 'title': _(u'Upload sources'), + 'paragraphs': [ + _(u'Not document sources have been defined or there are no sources enabled.') + # TODO: Add link to setup + ], + } + }) + + document_type_id = request.GET.get('document_type_id', None) + if document_type_id: + document_type = get_object_or_404(DocumentType, pk=document_type_id[0]) + else: + document_type = None + + subtemplates_list = [] + + if source_type is None and source_id is None: + if web_forms.count(): + source_type = web_forms[0].source_type + source_id = web_forms[0].pk + elif staging_folders.count(): + source_type = staging_folders[0].source_type + source_id = staging_folders[0].pk + + + if source_type and source_id: + if source_type == SOURCE_CHOICE_WEB_FORM: + web_form = get_object_or_404(WebForm, pk=source_id) + context['source'] = web_form + form = DocumentForm(document_type=document_type) + + subtemplates_list.append({ + 'name': 'generic_form_subtemplate.html', + 'context': { + 'form': form, + 'title': _(u'upload a local document from source: %s') % web_form.title, + }, + }) + elif source_type == SOURCE_CHOICE_STAGING: + staging_folder = get_object_or_404(StagingFolder, pk=source_id) + context['source'] = staging_folder + StagingFile = create_staging_file_class(request, staging_folder.folder_path) + form = StagingDocumentForm(cls=StagingFile, + document_type=document_type) + try: + staging_filelist = StagingFile.get_all() + except Exception, e: + messages.error(request, e) + staging_filelist = [] + finally: + subtemplates_list = [ + { + 'name': 'generic_form_subtemplate.html', + 'context': { + 'form': form, + 'title': _(u'upload a document from staging source: %s') % staging_folder.title, + } + }, + { + 'name': 'generic_list_subtemplate.html', + 'context': { + 'title': _(u'files in staging path'), + 'object_list': staging_filelist, + 'hide_link': True, + } + }, + ] + + + + + + + context.update({ + 'document_type_id': document_type_id, + 'subtemplates_list': subtemplates_list, + 'sidebar_subtemplates_list': [ + { + 'name': 'generic_subtemplate.html', + 'context': { + 'title': _(u'Current metadata'), + 'paragraphs': metadata_repr_as_list(decode_metadata_from_url(request.GET)), + 'side_bar': True, + } + }], + 'temporary_navigation_links': {'form_header': {'upload_interactive': {'links': tab_links}}} + }) + return render_to_response('generic_form.html', context, + context_instance=RequestContext(request)) + + +def _handle_save_document(request, document, form=None): + RecentDocument.objects.add_document_for_user(request.user, document) + + if form: + if form.cleaned_data['new_filename']: + document.file_filename = form.cleaned_data['new_filename'] + document.save() + + if form and 'document_type_available_filenames' in form.cleaned_data: + if form.cleaned_data['document_type_available_filenames']: + document.file_filename = form.cleaned_data['document_type_available_filenames'].filename + document.save() + + save_metadata_list(decode_metadata_from_url(request.GET), document, create=True) + + warnings = update_indexes(document) + if request.user.is_staff or request.user.is_superuser: + for warning in warnings: + messages.warning(request, warning) + + create_history(HISTORY_DOCUMENT_CREATED, document, {'user': request.user}) + + +def _handle_zip_file(request, uploaded_file, document_type=None): + filename = getattr(uploaded_file, 'filename', getattr(uploaded_file, 'name', '')) + if filename.lower().endswith('zip'): + zfobj = zipfile.ZipFile(uploaded_file) + for filename in zfobj.namelist(): + if not filename.endswith('/'): + zip_document = Document(file=SimpleUploadedFile( + name=filename, content=zfobj.read(filename))) + if document_type: + zip_document.document_type = document_type + zip_document.save() + _handle_save_document(request, zip_document) + messages.success(request, _(u'Extracted file: %s, uploaded successfully.') % filename) + #Signal that uploaded file was a zip file + return True + else: + #Otherwise tell parent to handle file + return False + + +def upload_document_with_type(request, source): + check_permissions(request.user, [PERMISSION_DOCUMENT_CREATE]) + + document_type_id = request.GET.get('document_type_id', None) + if document_type_id: + document_type = get_object_or_404(DocumentType, pk=document_type_id[0]) + else: + document_type = None + + if request.method == 'POST': + if source == UPLOAD_SOURCE_LOCAL: + form = DocumentForm(request.POST, request.FILES, document_type=document_type) + if form.is_valid(): + try: + expand = form.cleaned_data['expand'] + if (not expand) or (expand and not _handle_zip_file(request, request.FILES['file'], document_type)): + instance = form.save() + instance.save() + if document_type: + instance.document_type = document_type + _handle_save_document(request, instance, form) + messages.success(request, _(u'Document uploaded successfully.')) + except Exception, e: + messages.error(request, e) + + return HttpResponseRedirect(request.get_full_path()) + elif (USE_STAGING_DIRECTORY and source == UPLOAD_SOURCE_STAGING) or (PER_USER_STAGING_DIRECTORY and source == UPLOAD_SOURCE_USER_STAGING): + StagingFile = create_staging_file_class(request, source) + form = StagingDocumentForm(request.POST, + request.FILES, cls=StagingFile, + document_type=document_type) + if form.is_valid(): + try: + staging_file = StagingFile.get(form.cleaned_data['staging_file_id']) + expand = form.cleaned_data['expand'] + if (not expand) or (expand and not _handle_zip_file(request, staging_file.upload(), document_type)): + document = Document(file=staging_file.upload()) + if document_type: + document.document_type = document_type + document.save() + _handle_save_document(request, document, form) + messages.success(request, _(u'Staging file: %s, uploaded successfully.') % staging_file.filename) + + if DELETE_STAGING_FILE_AFTER_UPLOAD: + staging_file.delete() + messages.success(request, _(u'Staging file: %s, deleted successfully.') % staging_file.filename) + except Exception, e: + messages.error(request, e) + + return HttpResponseRedirect(request.META['HTTP_REFERER']) + else: + if source == UPLOAD_SOURCE_LOCAL: + form = DocumentForm(document_type=document_type) + elif (USE_STAGING_DIRECTORY and source == UPLOAD_SOURCE_STAGING) or (PER_USER_STAGING_DIRECTORY and source == UPLOAD_SOURCE_USER_STAGING): + StagingFile = create_staging_file_class(request, source) + form = StagingDocumentForm(cls=StagingFile, + document_type=document_type) + + subtemplates_list = [] + + if source == UPLOAD_SOURCE_LOCAL: + subtemplates_list.append({ + 'name': 'generic_form_subtemplate.html', + 'context': { + 'form': form, + 'title': _(u'upload a local document'), + }, + }) + + elif (USE_STAGING_DIRECTORY and source == UPLOAD_SOURCE_STAGING) or (PER_USER_STAGING_DIRECTORY and source == UPLOAD_SOURCE_USER_STAGING): + if source == UPLOAD_SOURCE_STAGING: + form_title = _(u'upload a document from staging') + list_title = _(u'files in staging') + else: + form_title = _(u'upload a document from user staging') + list_title = _(u'files in user staging') + try: + staging_filelist = StagingFile.get_all() + except Exception, e: + messages.error(request, e) + staging_filelist = [] + finally: + subtemplates_list = [ + { + 'name': 'generic_form_subtemplate.html', + 'context': { + 'form': form, + 'title': form_title, + } + }, + { + 'name': 'generic_list_subtemplate.html', + 'context': { + 'title': list_title, + 'object_list': staging_filelist, + 'hide_link': True, + } + }, + ] + + context = { + 'source': source, + 'document_type_id': document_type_id, + 'subtemplates_list': subtemplates_list, + 'sidebar_subtemplates_list': [ + { + 'name': 'generic_subtemplate.html', + 'context': { + 'title': _(u'Current metadata'), + 'paragraphs': metadata_repr_as_list(decode_metadata_from_url(request.GET)), + 'side_bar': True, + } + }] + } + return render_to_response('generic_form.html', context, + context_instance=RequestContext(request)) + + +def staging_file_preview(request, source_type, source_id, staging_file_id): + check_permissions(request.user, [PERMISSION_DOCUMENT_CREATE]) + staging_folder = get_object_or_404(StagingFolder, pk=source_id) + StagingFile = create_staging_file_class(request, staging_folder.folder_path) + try: + output_file, errors = StagingFile.get(staging_file_id).preview(staging_folder.get_preview_size()) + if errors and (request.user.is_staff or request.user.is_superuser): + for error in errors: + messages.warning(request, _(u'Staging file transformation error: %(error)s') % { + 'error': error + }) + + except UnkownConvertError, e: + if request.user.is_staff or request.user.is_superuser: + messages.error(request, e) + + output_file = os.path.join(settings.MEDIA_ROOT, u'images', PICTURE_ERROR_MEDIUM) + except UnknownFormat: + output_file = os.path.join(settings.MEDIA_ROOT, u'images', PICTURE_UNKNOWN_MEDIUM) + except Exception, e: + if request.user.is_staff or request.user.is_superuser: + messages.error(request, e) + output_file = os.path.join(settings.MEDIA_ROOT, u'images', PICTURE_ERROR_MEDIUM) + finally: + return sendfile.sendfile(request, output_file) + + +def staging_file_delete(request, source_type, source_id, staging_file_id): + check_permissions(request.user, [PERMISSION_DOCUMENT_CREATE]) + staging_folder = get_object_or_404(StagingFolder, pk=source_id) + StagingFile = create_staging_file_class(request, staging_folder.folder_path) + + staging_file = StagingFile.get(staging_file_id) + next = request.POST.get('next', request.GET.get('next', request.META.get('HTTP_REFERER', None))) + previous = request.POST.get('previous', request.GET.get('previous', request.META.get('HTTP_REFERER', None))) + + if request.method == 'POST': + try: + staging_file.delete() + messages.success(request, _(u'Staging file delete successfully.')) + except Exception, e: + messages.error(request, e) + return HttpResponseRedirect(next) + + return render_to_response('generic_confirm.html', { + 'source': staging_folder, + 'delete_view': True, + 'object': staging_file, + 'next': next, + 'previous': previous, + 'form_icon': u'delete.png', + }, context_instance=RequestContext(request)) diff --git a/urls.py b/urls.py index f8c245d097..86eedddb6f 100644 --- a/urls.py +++ b/urls.py @@ -25,6 +25,7 @@ urlpatterns = patterns('', (r'^document_indexing/', include('document_indexing.urls')), (r'^history/', include('history.urls')), (r'^converter/', include('converter.urls')), + (r'^sources/', include('sources.urls')), )