476 lines
18 KiB
Python
476 lines
18 KiB
Python
from __future__ import absolute_import, unicode_literals
|
|
|
|
from django.conf import settings
|
|
from django.contrib import messages
|
|
from django.core.exceptions import PermissionDenied
|
|
from django.core.urlresolvers import reverse
|
|
from django.http import HttpResponseRedirect
|
|
from django.shortcuts import render_to_response, get_object_or_404
|
|
from django.template import RequestContext
|
|
from django.utils.http import urlencode
|
|
from django.utils.translation import ugettext_lazy as _
|
|
|
|
from acls.models import AccessControlList
|
|
from common import menu_facet
|
|
from common.models import SharedUploadedFile
|
|
from common.utils import encapsulate
|
|
from common.views import MultiFormView, ParentChildListView
|
|
from documents.models import DocumentType, Document
|
|
from documents.permissions import (
|
|
permission_document_create, permission_document_new_version
|
|
)
|
|
from documents.tasks import task_upload_new_version
|
|
from metadata.api import decode_metadata_from_url
|
|
from navigation import Link
|
|
from permissions import Permission
|
|
|
|
from .forms import (
|
|
NewDocumentForm, NewVersionForm
|
|
)
|
|
from .literals import (
|
|
SOURCE_CHOICE_STAGING, SOURCE_CHOICE_WEB_FORM, SOURCE_UNCOMPRESS_CHOICE_ASK,
|
|
SOURCE_UNCOMPRESS_CHOICE_Y
|
|
)
|
|
from .models import (
|
|
InteractiveSource, Source, StagingFolderSource, WebFormSource
|
|
)
|
|
from .permissions import (
|
|
permission_sources_setup_create, permission_sources_setup_delete,
|
|
permission_sources_setup_edit, permission_sources_setup_view
|
|
)
|
|
from .tasks import task_source_upload_document
|
|
from .utils import get_class, get_form_class, get_upload_form_class
|
|
|
|
|
|
class SourceLogListView(ParentChildListView):
|
|
object_permission = permission_sources_setup_view
|
|
parent_queryset = Source.objects.select_subclasses()
|
|
|
|
def get_queryset(self):
|
|
return self.get_object().logs.all()
|
|
|
|
def get_context_data(self, **kwargs):
|
|
context = super(SourceLogListView, self).get_context_data(**kwargs)
|
|
|
|
context.update(
|
|
{
|
|
'title': _('Log entries for source: %s') % self.get_object(),
|
|
'hide_object': True,
|
|
'extra_columns': [
|
|
{
|
|
'name': _('Date time'),
|
|
'attribute': encapsulate(lambda entry: entry.datetime)
|
|
},
|
|
{
|
|
'name': _('Message'),
|
|
'attribute': encapsulate(lambda entry: entry.message)
|
|
},
|
|
]
|
|
}
|
|
)
|
|
|
|
return context
|
|
|
|
|
|
def document_create_siblings(request, document_id):
|
|
Permission.check_permissions(request.user, [permission_document_create])
|
|
|
|
document = get_object_or_404(Document, pk=document_id)
|
|
query_dict = {}
|
|
for pk, metadata in enumerate(document.metadata.all()):
|
|
query_dict['metadata%s_id' % pk] = metadata.metadata_type_id
|
|
query_dict['metadata%s_value' % pk] = metadata.value
|
|
|
|
query_dict['document_type_id'] = document.document_type_id
|
|
|
|
url = reverse('sources:upload_interactive')
|
|
return HttpResponseRedirect('%s?%s' % (url, urlencode(query_dict)))
|
|
|
|
|
|
def get_tab_link_for_source(source, document=None):
|
|
if document:
|
|
view = 'sources:upload_version'
|
|
args = ['"{}"'.format(document.pk), '"{}"'.format(source.pk)]
|
|
else:
|
|
view = 'sources:upload_interactive'
|
|
args = ['"{}"'.format(source.pk)]
|
|
|
|
return Link(
|
|
text=source.label,
|
|
view=view,
|
|
args=args,
|
|
keep_query=True,
|
|
remove_from_query=['page'],
|
|
icon='fa fa-upload',
|
|
)
|
|
|
|
|
|
def get_active_tab_links(document=None):
|
|
tab_links = []
|
|
|
|
web_forms = WebFormSource.objects.filter(enabled=True)
|
|
for web_form in web_forms:
|
|
tab_links.append(get_tab_link_for_source(web_form, document))
|
|
|
|
staging_folders = StagingFolderSource.objects.filter(enabled=True)
|
|
for staging_folder in staging_folders:
|
|
tab_links.append(get_tab_link_for_source(staging_folder, document))
|
|
|
|
return {
|
|
'tab_links': tab_links,
|
|
SOURCE_CHOICE_WEB_FORM: web_forms,
|
|
SOURCE_CHOICE_STAGING: staging_folders,
|
|
}
|
|
|
|
|
|
class UploadBaseView(MultiFormView):
|
|
template_name = 'appearance/generic_form.html'
|
|
prefixes = {'source_form': 'source', 'document_form': 'document'}
|
|
|
|
def dispatch(self, request, *args, **kwargs):
|
|
if 'source_id' in kwargs:
|
|
self.source = get_object_or_404(Source.objects.filter(enabled=True).select_subclasses(), pk=kwargs['source_id'])
|
|
else:
|
|
self.source = InteractiveSource.objects.filter(enabled=True).select_subclasses().first()
|
|
|
|
if InteractiveSource.objects.filter(enabled=True).count() == 0:
|
|
messages.error(request, _('No interactive document sources have been defined or none have been enabled, create one before proceeding.'))
|
|
return HttpResponseRedirect(reverse('sources:setup_source_list'))
|
|
|
|
return super(UploadBaseView, self).dispatch(request, *args, **kwargs)
|
|
|
|
def get_context_data(self, **kwargs):
|
|
context = super(UploadBaseView, self).get_context_data(**kwargs)
|
|
subtemplates_list = []
|
|
|
|
context['source'] = self.source
|
|
|
|
if isinstance(self.source, StagingFolderSource):
|
|
try:
|
|
staging_filelist = list(self.source.get_files())
|
|
except Exception as exception:
|
|
messages.error(self.request, exception)
|
|
staging_filelist = []
|
|
finally:
|
|
subtemplates_list = [
|
|
{
|
|
'name': 'appearance/generic_multiform_subtemplate.html',
|
|
'context': {
|
|
'forms': context['forms'],
|
|
'title': _('Document properties'),
|
|
}
|
|
},
|
|
{
|
|
'name': 'appearance/generic_list_subtemplate.html',
|
|
'context': {
|
|
'hide_link': True,
|
|
'object_list': staging_filelist,
|
|
'title': _('Files in staging path'),
|
|
}
|
|
},
|
|
]
|
|
else:
|
|
subtemplates_list.append({
|
|
'name': 'appearance/generic_multiform_subtemplate.html',
|
|
'context': {
|
|
'forms': context['forms'],
|
|
'is_multipart': True,
|
|
'title': _('Document properties'),
|
|
},
|
|
})
|
|
|
|
menu_facet.bound_links['sources:upload_interactive'] = self.tab_links['tab_links']
|
|
menu_facet.bound_links['sources:upload_version'] = self.tab_links['tab_links']
|
|
|
|
context.update({
|
|
'subtemplates_list': subtemplates_list,
|
|
})
|
|
|
|
return context
|
|
|
|
|
|
class UploadInteractiveView(UploadBaseView):
|
|
|
|
def dispatch(self, request, *args, **kwargs):
|
|
self.subtemplates_list = []
|
|
|
|
Permission.check_permissions(request.user, [permission_document_create])
|
|
|
|
self.document_type = get_object_or_404(DocumentType, pk=self.request.GET.get('document_type_id', self.request.POST.get('document_type_id')))
|
|
|
|
self.tab_links = get_active_tab_links()
|
|
|
|
return super(UploadInteractiveView, self).dispatch(request, *args, **kwargs)
|
|
|
|
def forms_valid(self, forms):
|
|
if self.source.uncompress == SOURCE_UNCOMPRESS_CHOICE_ASK:
|
|
expand = forms['source_form'].cleaned_data.get('expand')
|
|
else:
|
|
if self.source.uncompress == SOURCE_UNCOMPRESS_CHOICE_Y:
|
|
expand = True
|
|
else:
|
|
expand = False
|
|
|
|
uploaded_file = self.source.get_upload_file_object(forms['source_form'].cleaned_data)
|
|
|
|
shared_uploaded_file = SharedUploadedFile.objects.create(file=uploaded_file.file)
|
|
|
|
label = shared_uploaded_file.filename
|
|
if 'document_type_available_filenames' in forms['document_form'].cleaned_data:
|
|
if forms['document_form'].cleaned_data['document_type_available_filenames']:
|
|
label = forms['document_form'].cleaned_data['document_type_available_filenames'].filename
|
|
|
|
if not self.request.user.is_anonymous():
|
|
user_id = self.request.user.pk
|
|
else:
|
|
user_id = None
|
|
|
|
try:
|
|
self.source.clean_up_upload_file(uploaded_file)
|
|
except Exception as exception:
|
|
messages.error(self.request, exception)
|
|
|
|
task_source_upload_document.apply_async(kwargs=dict(
|
|
description=forms['document_form'].cleaned_data.get('description'),
|
|
document_type_id=self.document_type.pk,
|
|
expand=expand,
|
|
label=label,
|
|
language=forms['document_form'].cleaned_data.get('language'),
|
|
metadata_dict_list=decode_metadata_from_url(self.request.GET),
|
|
shared_uploaded_file_id=shared_uploaded_file.pk,
|
|
source_id=self.source.pk,
|
|
user_id=user_id,
|
|
), queue='uploads')
|
|
messages.success(self.request, _('New document queued for uploaded and will be available shortly.'))
|
|
return HttpResponseRedirect(self.request.get_full_path())
|
|
|
|
def create_source_form_form(self, **kwargs):
|
|
return self.get_form_classes()['source_form'](
|
|
prefix=kwargs['prefix'],
|
|
source=self.source,
|
|
show_expand=(self.source.uncompress == SOURCE_UNCOMPRESS_CHOICE_ASK),
|
|
data=kwargs.get('data', None),
|
|
files=kwargs.get('files', None),
|
|
)
|
|
|
|
def create_document_form_form(self, **kwargs):
|
|
return self.get_form_classes()['document_form'](
|
|
prefix=kwargs['prefix'],
|
|
document_type=self.document_type,
|
|
data=kwargs.get('data', None),
|
|
files=kwargs.get('files', None),
|
|
)
|
|
|
|
def get_form_classes(self):
|
|
return {'document_form': NewDocumentForm, 'source_form': get_upload_form_class(self.source.source_type)}
|
|
|
|
def get_context_data(self, **kwargs):
|
|
context = super(UploadInteractiveView, self).get_context_data(**kwargs)
|
|
context['title'] = _('Upload a local document from source: %s') % self.source.label
|
|
return context
|
|
|
|
|
|
class UploadInteractiveVersionView(UploadBaseView):
|
|
def dispatch(self, request, *args, **kwargs):
|
|
|
|
self.subtemplates_list = []
|
|
|
|
self.document = get_object_or_404(Document, pk=kwargs['document_pk'])
|
|
try:
|
|
Permission.check_permissions(self.request.user, [permission_document_new_version])
|
|
except PermissionDenied:
|
|
AccessControlList.objects.check_access(permission_document_new_version, self.request.user, self.document)
|
|
|
|
self.tab_links = get_active_tab_links(self.document)
|
|
|
|
return super(UploadInteractiveVersionView, self).dispatch(request, *args, **kwargs)
|
|
|
|
def forms_valid(self, forms):
|
|
uploaded_file = self.source.get_upload_file_object(forms['source_form'].cleaned_data)
|
|
|
|
shared_uploaded_file = SharedUploadedFile.objects.create(file=uploaded_file.file)
|
|
|
|
try:
|
|
self.source.clean_up_upload_file(uploaded_file)
|
|
except Exception as exception:
|
|
messages.error(self.request, exception)
|
|
|
|
if not self.request.user.is_anonymous():
|
|
user_id = self.request.user.pk
|
|
else:
|
|
user_id = None
|
|
|
|
task_upload_new_version.apply_async(kwargs=dict(
|
|
shared_uploaded_file_id=shared_uploaded_file.pk,
|
|
document_id=self.document.pk,
|
|
user_id=user_id,
|
|
comment=forms['document_form'].cleaned_data.get('comment')
|
|
), queue='uploads')
|
|
|
|
messages.success(self.request, _('New document version queued for uploaded and will be available shortly.'))
|
|
return HttpResponseRedirect(reverse('documents:document_version_list', args=[self.document.pk]))
|
|
|
|
def create_source_form_form(self, **kwargs):
|
|
return self.get_form_classes()['source_form'](
|
|
prefix=kwargs['prefix'],
|
|
source=self.source,
|
|
show_expand=False,
|
|
data=kwargs.get('data', None),
|
|
files=kwargs.get('files', None),
|
|
)
|
|
|
|
def create_document_form_form(self, **kwargs):
|
|
return self.get_form_classes()['document_form'](
|
|
prefix=kwargs['prefix'],
|
|
data=kwargs.get('data', None),
|
|
files=kwargs.get('files', None),
|
|
)
|
|
|
|
def get_form_classes(self):
|
|
return {'document_form': NewVersionForm, 'source_form': get_upload_form_class(self.source.source_type)}
|
|
|
|
def get_context_data(self, **kwargs):
|
|
context = super(UploadInteractiveVersionView, self).get_context_data(**kwargs)
|
|
context['object'] = self.document
|
|
context['title'] = _('Upload a new version from source: %s') % self.source.label
|
|
|
|
return context
|
|
|
|
|
|
def staging_file_delete(request, staging_folder_pk, encoded_filename):
|
|
Permission.check_permissions(request.user, [permission_document_create, permission_document_new_version])
|
|
staging_folder = get_object_or_404(StagingFolderSource, pk=staging_folder_pk)
|
|
|
|
staging_file = staging_folder.get_file(encoded_filename=encoded_filename)
|
|
next = request.POST.get('next', request.GET.get('next', request.META.get('HTTP_REFERER', reverse(settings.LOGIN_REDIRECT_URL))))
|
|
previous = request.POST.get('previous', request.GET.get('previous', request.META.get('HTTP_REFERER', reverse(settings.LOGIN_REDIRECT_URL))))
|
|
|
|
if request.method == 'POST':
|
|
try:
|
|
staging_file.delete()
|
|
messages.success(request, _('Staging file delete successfully.'))
|
|
except Exception as exception:
|
|
messages.error(request, _('Staging file delete error; %s.') % exception)
|
|
return HttpResponseRedirect(next)
|
|
|
|
results = get_active_tab_links()
|
|
|
|
return render_to_response('appearance/generic_confirm.html', {
|
|
'source': staging_folder,
|
|
'delete_view': True,
|
|
'object': staging_file,
|
|
'next': next,
|
|
'previous': previous,
|
|
'extra_navigation_links': {'form_header': {'staging_file_delete': {'links': results['tab_links']}}},
|
|
}, context_instance=RequestContext(request))
|
|
|
|
|
|
# Setup views
|
|
def setup_source_list(request):
|
|
Permission.check_permissions(request.user, [permission_sources_setup_view])
|
|
|
|
context = {
|
|
'object_list': Source.objects.select_subclasses(),
|
|
'title': _('Sources'),
|
|
'hide_link': True,
|
|
'extra_columns': [
|
|
{
|
|
'name': _('Type'),
|
|
'attribute': encapsulate(lambda x: x.class_fullname())
|
|
},
|
|
{
|
|
'name': _('Enabled'),
|
|
'attribute': encapsulate(lambda x: _('Yes') if x.enabled else _('No'))
|
|
},
|
|
]
|
|
}
|
|
|
|
return render_to_response('appearance/generic_list.html', context,
|
|
context_instance=RequestContext(request))
|
|
|
|
|
|
def setup_source_edit(request, source_id):
|
|
Permission.check_permissions(request.user, [permission_sources_setup_edit])
|
|
|
|
source = get_object_or_404(Source.objects.select_subclasses(), pk=source_id)
|
|
form_class = get_form_class(source.source_type)
|
|
|
|
next = request.POST.get('next', request.GET.get('next', request.META.get('HTTP_REFERER', reverse(settings.LOGIN_REDIRECT_URL))))
|
|
|
|
if request.method == 'POST':
|
|
form = form_class(instance=source, data=request.POST)
|
|
if form.is_valid():
|
|
try:
|
|
form.save()
|
|
messages.success(request, _('Source edited successfully'))
|
|
return HttpResponseRedirect(next)
|
|
except Exception as exception:
|
|
messages.error(request, _('Error editing source; %s') % exception)
|
|
else:
|
|
form = form_class(instance=source)
|
|
|
|
return render_to_response('appearance/generic_form.html', {
|
|
'form': form,
|
|
'navigation_object_list': ['source'],
|
|
'next': next,
|
|
'source': source,
|
|
'source_type': source.source_type,
|
|
'title': _('Edit source: %s') % source,
|
|
}, context_instance=RequestContext(request))
|
|
|
|
|
|
def setup_source_delete(request, source_id):
|
|
Permission.check_permissions(request.user, [permission_sources_setup_delete])
|
|
source = get_object_or_404(Source.objects.select_subclasses(), pk=source_id)
|
|
redirect_view = reverse('sources:setup_source_list')
|
|
|
|
previous = request.POST.get('previous', request.GET.get('previous', request.META.get('HTTP_REFERER', redirect_view)))
|
|
|
|
if request.method == 'POST':
|
|
try:
|
|
source.delete()
|
|
messages.success(request, _('Source "%s" deleted successfully.') % source)
|
|
except Exception as exception:
|
|
messages.error(request, _('Error deleting source "%(source)s": %(error)s') % {
|
|
'source': source, 'error': exception
|
|
})
|
|
return HttpResponseRedirect(redirect_view)
|
|
|
|
context = {
|
|
'delete_view': True,
|
|
'navigation_object_list': ['source'],
|
|
'previous': previous,
|
|
'source': source,
|
|
'source_type': source.source_type,
|
|
'title': _('Are you sure you wish to delete the source: %s?') % source,
|
|
}
|
|
|
|
return render_to_response('appearance/generic_confirm.html', context,
|
|
context_instance=RequestContext(request))
|
|
|
|
|
|
def setup_source_create(request, source_type):
|
|
Permission.check_permissions(request.user, [permission_sources_setup_create])
|
|
|
|
cls = get_class(source_type)
|
|
form_class = get_form_class(source_type)
|
|
|
|
if request.method == 'POST':
|
|
form = form_class(data=request.POST)
|
|
if form.is_valid():
|
|
try:
|
|
form.save()
|
|
messages.success(request, _('Source created successfully'))
|
|
return HttpResponseRedirect(reverse('sources:setup_source_list'))
|
|
except Exception as exception:
|
|
messages.error(request, _('Error creating source; %s') % exception)
|
|
else:
|
|
form = form_class()
|
|
|
|
return render_to_response('appearance/generic_form.html', {
|
|
'form': form,
|
|
'navigation_object_list': ['source'],
|
|
'source_type': source_type,
|
|
'title': _('Create new source of type: %s') % cls.class_fullname(),
|
|
}, context_instance=RequestContext(request))
|