Add new document upload wizard step to attach tags. GitLab issue #208.
This commit is contained in:
@@ -63,6 +63,12 @@
|
||||
<div class="radio">
|
||||
{% render_field field %}
|
||||
</div>
|
||||
{% elif field|widget_type == 'checkboxselectmultiple' %}
|
||||
{% for option in field %}
|
||||
<div class="checkbox">
|
||||
{{ option.render }}
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% else %}
|
||||
{% render_field field class+="form-control" %}
|
||||
{% endif %}
|
||||
|
||||
@@ -36,3 +36,8 @@ DEFAULT_METADATA_ATTACHMENT_NAME = 'metadata.yaml'
|
||||
DEFAULT_POP3_TIMEOUT = 60
|
||||
DEFAULT_IMAP_MAILBOX = 'INBOX'
|
||||
DEFAULT_SOURCE_TASK_RETRY_DELAY = 10
|
||||
|
||||
# Upload wizard steps
|
||||
STEP_DOCUMENT_TYPE = '0'
|
||||
STEP_METADATA = '1'
|
||||
STEP_TAGS = '2'
|
||||
|
||||
@@ -28,6 +28,7 @@ from documents.models import Document, DocumentType
|
||||
from documents.settings import setting_language
|
||||
from metadata.api import save_metadata_list, set_bulk_metadata
|
||||
from metadata.models import MetadataType
|
||||
from tags.models import Tag
|
||||
|
||||
from .classes import Attachment, SourceUploadedFile, StagingFile
|
||||
from .literals import (
|
||||
@@ -59,7 +60,7 @@ class Source(models.Model):
|
||||
def fullname(self):
|
||||
return ' '.join([self.class_fullname(), '"%s"' % self.label])
|
||||
|
||||
def upload_document(self, file_object, document_type, description=None, label=None, language=None, metadata_dict_list=None, metadata_dictionary=None, user=None):
|
||||
def upload_document(self, file_object, document_type, description=None, label=None, language=None, metadata_dict_list=None, metadata_dictionary=None, tag_ids=None, user=None):
|
||||
try:
|
||||
with transaction.atomic():
|
||||
document = Document.objects.create(
|
||||
@@ -88,6 +89,10 @@ class Source(models.Model):
|
||||
metadata_dictionary=metadata_dictionary
|
||||
)
|
||||
|
||||
if tag_ids:
|
||||
for tag in Tag.objects.filter(pk__in=tag_ids):
|
||||
tag.documents.add(document)
|
||||
|
||||
except Exception as exception:
|
||||
logger.critical(
|
||||
'Unexpected exception while trying to create new document '
|
||||
|
||||
@@ -35,7 +35,7 @@ def task_check_interval_source(source_id):
|
||||
|
||||
|
||||
@app.task(bind=True, default_retry_delay=DEFAULT_SOURCE_TASK_RETRY_DELAY, ignore_result=True)
|
||||
def task_upload_document(self, source_id, document_type_id, shared_uploaded_file_id, description=None, label=None, language=None, metadata_dict_list=None, user_id=None):
|
||||
def task_upload_document(self, source_id, document_type_id, shared_uploaded_file_id, description=None, label=None, language=None, metadata_dict_list=None, tag_ids=None, user_id=None):
|
||||
SharedUploadedFile = apps.get_model(
|
||||
app_label='common', model_name='SharedUploadedFile'
|
||||
)
|
||||
@@ -64,7 +64,8 @@ def task_upload_document(self, source_id, document_type_id, shared_uploaded_file
|
||||
source.upload_document(
|
||||
file_object=file_object, document_type=document_type,
|
||||
description=description, label=label, language=language,
|
||||
metadata_dict_list=metadata_dict_list, user=user
|
||||
metadata_dict_list=metadata_dict_list, user=user,
|
||||
tag_ids=tag_ids
|
||||
)
|
||||
|
||||
except OperationalError as exception:
|
||||
@@ -85,7 +86,7 @@ def task_upload_document(self, source_id, document_type_id, shared_uploaded_file
|
||||
|
||||
|
||||
@app.task(bind=True, default_retry_delay=DEFAULT_SOURCE_TASK_RETRY_DELAY, ignore_result=True)
|
||||
def task_source_handle_upload(self, document_type_id, shared_uploaded_file_id, source_id, description=None, expand=False, label=None, language=None, metadata_dict_list=None, skip_list=None, user_id=None):
|
||||
def task_source_handle_upload(self, document_type_id, shared_uploaded_file_id, source_id, description=None, expand=False, label=None, language=None, metadata_dict_list=None, skip_list=None, tag_ids=None, user_id=None):
|
||||
SharedUploadedFile = apps.get_model(
|
||||
app_label='common', model_name='SharedUploadedFile'
|
||||
)
|
||||
@@ -114,7 +115,7 @@ def task_source_handle_upload(self, document_type_id, shared_uploaded_file_id, s
|
||||
'description': description, 'document_type_id': document_type.pk,
|
||||
'label': label, 'language': language,
|
||||
'metadata_dict_list': metadata_dict_list,
|
||||
'source_id': source_id, 'user_id': user_id
|
||||
'source_id': source_id, 'tag_ids': tag_ids, 'user_id': user_id
|
||||
}
|
||||
|
||||
if not skip_list:
|
||||
@@ -147,7 +148,8 @@ def task_source_handle_upload(self, document_type_id, shared_uploaded_file_id, s
|
||||
expand=expand, label=label,
|
||||
language=language,
|
||||
metadata_dict_list=metadata_dict_list,
|
||||
skip_list=skip_list, user_id=user_id
|
||||
skip_list=skip_list, tag_ids=tag_ids,
|
||||
user_id=user_id
|
||||
)
|
||||
return
|
||||
else:
|
||||
|
||||
@@ -264,6 +264,7 @@ class UploadInteractiveView(UploadBaseView):
|
||||
metadata_dict_list=decode_metadata_from_url(self.request.GET),
|
||||
shared_uploaded_file_id=shared_uploaded_file.pk,
|
||||
source_id=self.source.pk,
|
||||
tag_ids=self.request.GET.getlist('tags'),
|
||||
user_id=user_id,
|
||||
))
|
||||
messages.success(
|
||||
|
||||
@@ -12,26 +12,39 @@ from common.mixins import ViewPermissionCheckMixin
|
||||
from documents.forms import DocumentTypeSelectForm
|
||||
from documents.permissions import permission_document_create
|
||||
from metadata.forms import MetadataFormSet
|
||||
from tags.forms import TagMultipleSelectionForm
|
||||
|
||||
from .literals import STEP_DOCUMENT_TYPE, STEP_METADATA, STEP_TAGS
|
||||
from .models import InteractiveSource
|
||||
|
||||
|
||||
def has_metadata_types(wizard):
|
||||
"""
|
||||
Skip the 2nd step if document type has no associated metadata
|
||||
"""
|
||||
|
||||
cleaned_data = wizard.get_cleaned_data_for_step(STEP_DOCUMENT_TYPE) or {}
|
||||
|
||||
document_type = cleaned_data.get('document_type')
|
||||
|
||||
if document_type:
|
||||
return document_type.metadata.exists()
|
||||
|
||||
|
||||
class DocumentCreateWizard(ViewPermissionCheckMixin, SessionWizardView):
|
||||
form_list = (DocumentTypeSelectForm, MetadataFormSet)
|
||||
template_name = 'appearance/generic_wizard.html'
|
||||
condition_dict = {STEP_METADATA: has_metadata_types}
|
||||
extra_context = {}
|
||||
form_list = (DocumentTypeSelectForm, MetadataFormSet, TagMultipleSelectionForm)
|
||||
form_titles = {
|
||||
DocumentTypeSelectForm: _('Step 1 of 3: Select document type'),
|
||||
MetadataFormSet: _('Step 2 of 3: Enter document metadata'),
|
||||
TagMultipleSelectionForm: _('Step 3 of 3: Select tags'),
|
||||
}
|
||||
template_name = 'appearance/generic_wizard.html'
|
||||
view_permission = permission_document_create
|
||||
|
||||
@staticmethod
|
||||
def _has_metadata_types(wizard):
|
||||
# Skip the 2nd step if document type has no associated metadata
|
||||
try:
|
||||
return wizard.get_cleaned_data_for_step('0')['document_type'].metadata.all().count()
|
||||
except TypeError:
|
||||
return False
|
||||
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
if InteractiveSource.objects.filter(enabled=True).count() == 0:
|
||||
if not InteractiveSource.objects.filter(enabled=True).exists():
|
||||
messages.error(
|
||||
request,
|
||||
_(
|
||||
@@ -40,59 +53,67 @@ class DocumentCreateWizard(ViewPermissionCheckMixin, SessionWizardView):
|
||||
)
|
||||
)
|
||||
return HttpResponseRedirect(reverse('sources:setup_source_list'))
|
||||
|
||||
return super(
|
||||
DocumentCreateWizard, self
|
||||
).dispatch(request, *args, **kwargs)
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(DocumentCreateWizard, self).__init__(*args, **kwargs)
|
||||
|
||||
self.condition_dict = {'1': DocumentCreateWizard._has_metadata_types}
|
||||
|
||||
self.step_titles = [
|
||||
_('Step 1 of 2: Select document type'),
|
||||
_('Step 2 of 2: Enter document metadata'),
|
||||
]
|
||||
|
||||
def get_form_initial(self, step):
|
||||
if step == '1':
|
||||
initial = []
|
||||
|
||||
for document_type_metadata_type in self.get_cleaned_data_for_step('0')['document_type'].metadata.all():
|
||||
initial.append({
|
||||
'document_type': self.get_cleaned_data_for_step('0')['document_type'],
|
||||
'metadata_type': document_type_metadata_type.metadata_type,
|
||||
})
|
||||
|
||||
return initial
|
||||
return self.initial_dict.get(step, {})
|
||||
|
||||
def get_context_data(self, form, **kwargs):
|
||||
context = super(
|
||||
DocumentCreateWizard, self
|
||||
).get_context_data(form=form, **kwargs)
|
||||
|
||||
context.update({
|
||||
'step_title': self.step_titles[self.steps.step0],
|
||||
'step_title': self.form_titles[form.__class__],
|
||||
'submit_label': _('Next step'),
|
||||
'submit_icon': 'fa fa-arrow-right',
|
||||
'title': _('Document upload wizard'),
|
||||
})
|
||||
return context
|
||||
|
||||
def get_form_initial(self, step):
|
||||
if step == STEP_METADATA:
|
||||
initial = []
|
||||
|
||||
for document_type_metadata_type in self.get_cleaned_data_for_step(STEP_DOCUMENT_TYPE)['document_type'].metadata.all():
|
||||
initial.append(
|
||||
{
|
||||
'document_type': self.get_cleaned_data_for_step(STEP_DOCUMENT_TYPE)['document_type'],
|
||||
'metadata_type': document_type_metadata_type.metadata_type,
|
||||
}
|
||||
)
|
||||
|
||||
return initial
|
||||
return self.initial_dict.get(step, {})
|
||||
|
||||
def get_form_kwargs(self, step):
|
||||
# Tags form needs the user instance to determine which tags to
|
||||
# display
|
||||
if step == STEP_TAGS:
|
||||
return {'user': self.request.user}
|
||||
|
||||
return {}
|
||||
|
||||
def done(self, *args, **kwargs):
|
||||
query_dict = {}
|
||||
|
||||
try:
|
||||
query_dict['document_type_id'] = self.get_cleaned_data_for_step('0')['document_type'].pk
|
||||
query_dict['document_type_id'] = self.get_cleaned_data_for_step(STEP_DOCUMENT_TYPE)['document_type'].pk
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
try:
|
||||
for identifier, metadata in enumerate(self.get_cleaned_data_for_step('1')):
|
||||
for identifier, metadata in enumerate(self.get_cleaned_data_for_step(STEP_METADATA)):
|
||||
query_dict['metadata%s_id' % identifier] = metadata['id']
|
||||
query_dict['metadata%s_value' % identifier] = metadata['value']
|
||||
except TypeError:
|
||||
pass
|
||||
|
||||
try:
|
||||
query_dict['tags'] = self.get_cleaned_data_for_step(STEP_TAGS)['tags']
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
url = '?'.join(
|
||||
[
|
||||
reverse('sources:upload_interactive'),
|
||||
|
||||
@@ -32,3 +32,24 @@ class TagListForm(forms.Form):
|
||||
self.fields['tag'] = forms.ModelChoiceField(
|
||||
queryset=queryset,
|
||||
label=_('Tags'))
|
||||
|
||||
|
||||
class TagMultipleSelectionForm(forms.Form):
|
||||
def __init__(self, *args, **kwargs):
|
||||
user = kwargs.pop('user', None)
|
||||
logger.debug('user: %s', user)
|
||||
super(TagMultipleSelectionForm, self).__init__(*args, **kwargs)
|
||||
|
||||
queryset = Tag.objects.all()
|
||||
try:
|
||||
Permission.check_permissions(user, (permission_tag_view,))
|
||||
except PermissionDenied:
|
||||
queryset = AccessControlList.objects.filter_by_access(
|
||||
permission_tag_view, user, queryset
|
||||
)
|
||||
|
||||
self.fields['tags'] = forms.MultipleChoiceField(
|
||||
label=_('Tags'), choices=queryset.values_list('id', 'label'),
|
||||
help_text=_('Tags to attach to the document.'),required=False,
|
||||
widget=forms.CheckboxSelectMultiple
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user