Add new WizardStep class to decouple the wizard step configuration.
Signed-off-by: Michael Price <loneviking72@gmail.com>
This commit is contained in:
committed by
Roberto Rosario
parent
a23f26f4f4
commit
460d747424
@@ -51,6 +51,7 @@ Next (2018-XX-XX)
|
|||||||
- Move the page count display to the top of the image.
|
- Move the page count display to the top of the image.
|
||||||
- Unify the way to gather the project's metadata. Use mayan.__XX__ and a new common tag named {% project_information '' %}
|
- Unify the way to gather the project's metadata. Use mayan.__XX__ and a new common tag named {% project_information '' %}
|
||||||
- Return to the same source view after uploading a document.
|
- Return to the same source view after uploading a document.
|
||||||
|
- Add new WizardStep class to decouple the wizard step configuration.
|
||||||
|
|
||||||
2.8 (2018-02-27)
|
2.8 (2018-02-27)
|
||||||
================
|
================
|
||||||
|
|||||||
@@ -64,8 +64,3 @@ DEFAULT_METADATA_ATTACHMENT_NAME = 'metadata.yaml'
|
|||||||
DEFAULT_POP3_TIMEOUT = 60
|
DEFAULT_POP3_TIMEOUT = 60
|
||||||
DEFAULT_IMAP_MAILBOX = 'INBOX'
|
DEFAULT_IMAP_MAILBOX = 'INBOX'
|
||||||
DEFAULT_SOURCE_TASK_RETRY_DELAY = 10
|
DEFAULT_SOURCE_TASK_RETRY_DELAY = 10
|
||||||
|
|
||||||
# Upload wizard steps
|
|
||||||
STEP_DOCUMENT_TYPE = '0'
|
|
||||||
STEP_METADATA = '1'
|
|
||||||
STEP_TAGS = '2'
|
|
||||||
|
|||||||
@@ -242,18 +242,20 @@ class UploadInteractiveView(UploadBaseView):
|
|||||||
except Exception as exception:
|
except Exception as exception:
|
||||||
messages.error(self.request, exception)
|
messages.error(self.request, exception)
|
||||||
|
|
||||||
task_source_handle_upload.apply_async(kwargs=dict(
|
task_source_handle_upload.apply_async(
|
||||||
description=forms['document_form'].cleaned_data.get('description'),
|
kwargs=dict(
|
||||||
document_type_id=self.document_type.pk,
|
description=forms['document_form'].cleaned_data.get('description'),
|
||||||
expand=expand,
|
document_type_id=self.document_type.pk,
|
||||||
label=label,
|
expand=expand,
|
||||||
language=forms['document_form'].cleaned_data.get('language'),
|
label=label,
|
||||||
metadata_dict_list=decode_metadata_from_url(self.request.GET),
|
language=forms['document_form'].cleaned_data.get('language'),
|
||||||
shared_uploaded_file_id=shared_uploaded_file.pk,
|
metadata_dict_list=decode_metadata_from_url(self.request.GET),
|
||||||
source_id=self.source.pk,
|
shared_uploaded_file_id=shared_uploaded_file.pk,
|
||||||
tag_ids=self.request.GET.getlist('tags'),
|
source_id=self.source.pk,
|
||||||
user_id=user_id,
|
tag_ids=self.request.GET.getlist('tags'),
|
||||||
))
|
user_id=user_id,
|
||||||
|
)
|
||||||
|
)
|
||||||
messages.success(
|
messages.success(
|
||||||
self.request,
|
self.request,
|
||||||
_(
|
_(
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ from __future__ import unicode_literals
|
|||||||
from django.contrib import messages
|
from django.contrib import messages
|
||||||
from django.http import HttpResponseRedirect
|
from django.http import HttpResponseRedirect
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
|
from django.utils.decorators import classonlymethod
|
||||||
from django.utils.encoding import force_text
|
from django.utils.encoding import force_text
|
||||||
from django.utils.http import urlencode
|
from django.utils.http import urlencode
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
@@ -13,37 +14,163 @@ from common.mixins import ViewPermissionCheckMixin
|
|||||||
from documents.forms import DocumentTypeSelectForm
|
from documents.forms import DocumentTypeSelectForm
|
||||||
from metadata.forms import DocumentMetadataFormSet
|
from metadata.forms import DocumentMetadataFormSet
|
||||||
from tags.forms import TagMultipleSelectionForm
|
from tags.forms import TagMultipleSelectionForm
|
||||||
|
from tags.models import Tag
|
||||||
|
|
||||||
from .literals import STEP_DOCUMENT_TYPE, STEP_METADATA, STEP_TAGS
|
|
||||||
from .models import InteractiveSource
|
from .models import InteractiveSource
|
||||||
|
|
||||||
|
|
||||||
def has_metadata_types(wizard):
|
class WizardStep(object):
|
||||||
"""
|
_registry = {}
|
||||||
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')
|
@classmethod
|
||||||
|
def done(cls, wizard):
|
||||||
|
return {}
|
||||||
|
|
||||||
if document_type:
|
@classmethod
|
||||||
return document_type.metadata.exists()
|
def get(cls, name):
|
||||||
|
return cls._registry[name]
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_all(cls):
|
||||||
|
return sorted(
|
||||||
|
cls._registry.values(), key=lambda x: x.number
|
||||||
|
)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_choices(cls, attribute_name):
|
||||||
|
return sorted(
|
||||||
|
[
|
||||||
|
(step.name, getattr(step, attribute_name)) for step in cls.get_all()
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_form_initial(cls, wizard):
|
||||||
|
return {}
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_form_kwargs(cls, wizard):
|
||||||
|
return {}
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def register(cls, step):
|
||||||
|
cls._registry[step.name] = step
|
||||||
|
|
||||||
|
|
||||||
|
class WizardStepDocumentType(WizardStep):
|
||||||
|
form_class = DocumentTypeSelectForm
|
||||||
|
label = _('Select document type')
|
||||||
|
name = 'document_type_selection'
|
||||||
|
number = 0
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def condition(cls, wizard):
|
||||||
|
return True
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def done(cls, wizard):
|
||||||
|
cleaned_data = wizard.get_cleaned_data_for_step(cls.name)
|
||||||
|
if cleaned_data:
|
||||||
|
return {
|
||||||
|
'document_type_id': cleaned_data['document_type'].pk
|
||||||
|
}
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_form_kwargs(cls, wizard):
|
||||||
|
return {'user': wizard.request.user}
|
||||||
|
|
||||||
|
|
||||||
|
class WizardStepMetadata(WizardStep):
|
||||||
|
form_class = DocumentMetadataFormSet
|
||||||
|
label = _('Enter document metadata')
|
||||||
|
name = 'metadata_entry'
|
||||||
|
number = 1
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def condition(cls, wizard):
|
||||||
|
"""
|
||||||
|
Skip step if document type has no associated metadata
|
||||||
|
"""
|
||||||
|
cleaned_data = wizard.get_cleaned_data_for_step(WizardStepDocumentType.name) or {}
|
||||||
|
|
||||||
|
document_type = cleaned_data.get('document_type')
|
||||||
|
|
||||||
|
if document_type:
|
||||||
|
return document_type.metadata.exists()
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_form_initial(cls, wizard):
|
||||||
|
initial = []
|
||||||
|
|
||||||
|
step_data = wizard.get_cleaned_data_for_step(WizardStepDocumentType.name)
|
||||||
|
if step_data:
|
||||||
|
document_type = step_data['document_type']
|
||||||
|
for document_type_metadata_type in document_type.metadata.all():
|
||||||
|
initial.append(
|
||||||
|
{
|
||||||
|
'document_type': document_type,
|
||||||
|
'metadata_type': document_type_metadata_type.metadata_type,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
return initial
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def done(cls, wizard):
|
||||||
|
result = {}
|
||||||
|
cleaned_data = wizard.get_cleaned_data_for_step(cls.name)
|
||||||
|
if cleaned_data:
|
||||||
|
for identifier, metadata in enumerate(wizard.get_cleaned_data_for_step(cls.name)):
|
||||||
|
if metadata.get('update'):
|
||||||
|
result['metadata%s_id' % identifier] = metadata['id']
|
||||||
|
result['metadata%s_value' % identifier] = metadata['value']
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
class WizardStepTags(WizardStep):
|
||||||
|
form_class = TagMultipleSelectionForm
|
||||||
|
label = _('Select tags')
|
||||||
|
name = 'tag_selection'
|
||||||
|
number = 2
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def condition(cls, wizard):
|
||||||
|
return Tag.objects.exists()
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_form_kwargs(self, wizard):
|
||||||
|
return {
|
||||||
|
'help_text': _('Tags to be attached.'),
|
||||||
|
'user': wizard.request.user
|
||||||
|
}
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def done(cls, wizard):
|
||||||
|
result = {}
|
||||||
|
cleaned_data = wizard.get_cleaned_data_for_step(cls.name)
|
||||||
|
if cleaned_data:
|
||||||
|
result['tags'] = [
|
||||||
|
force_text(tag.pk) for tag in cleaned_data['tags']
|
||||||
|
]
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
WizardStep.register(WizardStepDocumentType)
|
||||||
|
WizardStep.register(WizardStepMetadata)
|
||||||
|
WizardStep.register(WizardStepTags)
|
||||||
|
|
||||||
|
|
||||||
class DocumentCreateWizard(ViewPermissionCheckMixin, SessionWizardView):
|
class DocumentCreateWizard(ViewPermissionCheckMixin, SessionWizardView):
|
||||||
condition_dict = {STEP_METADATA: has_metadata_types}
|
|
||||||
extra_context = {}
|
|
||||||
form_list = (
|
|
||||||
DocumentTypeSelectForm, DocumentMetadataFormSet,
|
|
||||||
TagMultipleSelectionForm
|
|
||||||
)
|
|
||||||
form_titles = {
|
|
||||||
DocumentTypeSelectForm: _('Step 1 of 3: Select document type'),
|
|
||||||
DocumentMetadataFormSet: _('Step 2 of 3: Enter document metadata'),
|
|
||||||
TagMultipleSelectionForm: _('Step 3 of 3: Select tags'),
|
|
||||||
}
|
|
||||||
template_name = 'appearance/generic_wizard.html'
|
template_name = 'appearance/generic_wizard.html'
|
||||||
|
|
||||||
|
@classonlymethod
|
||||||
|
def as_view(cls, *args, **kwargs):
|
||||||
|
cls.form_list = WizardStep.get_choices(attribute_name='form_class')
|
||||||
|
cls.condition_dict = dict(WizardStep.get_choices(attribute_name='condition'))
|
||||||
|
return super(DocumentCreateWizard, cls).as_view(*args, **kwargs)
|
||||||
|
|
||||||
def dispatch(self, request, *args, **kwargs):
|
def dispatch(self, request, *args, **kwargs):
|
||||||
if not InteractiveSource.objects.filter(enabled=True).exists():
|
if not InteractiveSource.objects.filter(enabled=True).exists():
|
||||||
messages.error(
|
messages.error(
|
||||||
@@ -64,8 +191,15 @@ class DocumentCreateWizard(ViewPermissionCheckMixin, SessionWizardView):
|
|||||||
DocumentCreateWizard, self
|
DocumentCreateWizard, self
|
||||||
).get_context_data(form=form, **kwargs)
|
).get_context_data(form=form, **kwargs)
|
||||||
|
|
||||||
|
wizard_step = WizardStep.get(name=self.steps.current)
|
||||||
|
|
||||||
context.update({
|
context.update({
|
||||||
'step_title': self.form_titles[form.__class__],
|
'step_title': _(
|
||||||
|
'Step %(step)d of %(total_steps)d: %(step_label)s'
|
||||||
|
) % {
|
||||||
|
'step': self.steps.step1, 'total_steps': len(self.form_list),
|
||||||
|
'step_label': wizard_step.label,
|
||||||
|
},
|
||||||
'submit_label': _('Next step'),
|
'submit_label': _('Next step'),
|
||||||
'submit_icon': 'fa fa-arrow-right',
|
'submit_icon': 'fa fa-arrow-right',
|
||||||
'title': _('Document upload wizard'),
|
'title': _('Document upload wizard'),
|
||||||
@@ -73,55 +207,16 @@ class DocumentCreateWizard(ViewPermissionCheckMixin, SessionWizardView):
|
|||||||
return context
|
return context
|
||||||
|
|
||||||
def get_form_initial(self, step):
|
def get_form_initial(self, step):
|
||||||
if step == STEP_METADATA:
|
return WizardStep.get(name=step).get_form_initial(wizard=self) or {}
|
||||||
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):
|
def get_form_kwargs(self, step):
|
||||||
# Tags form needs the user instance to determine which tags to
|
return WizardStep.get(name=step).get_form_kwargs(wizard=self) or {}
|
||||||
# display
|
|
||||||
if step == STEP_DOCUMENT_TYPE:
|
|
||||||
return {'user': self.request.user}
|
|
||||||
|
|
||||||
if step == STEP_TAGS:
|
def done(self, form_list, **kwargs):
|
||||||
return {
|
|
||||||
'help_text': _('Tags to be attached.'),
|
|
||||||
'user': self.request.user
|
|
||||||
}
|
|
||||||
|
|
||||||
return {}
|
|
||||||
|
|
||||||
def done(self, *args, **kwargs):
|
|
||||||
query_dict = {}
|
query_dict = {}
|
||||||
|
|
||||||
try:
|
for step in WizardStep.get_all():
|
||||||
query_dict['document_type_id'] = self.get_cleaned_data_for_step(STEP_DOCUMENT_TYPE)['document_type'].pk
|
query_dict.update(step.done(wizard=self) or {})
|
||||||
except AttributeError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
try:
|
|
||||||
for identifier, metadata in enumerate(self.get_cleaned_data_for_step(STEP_METADATA)):
|
|
||||||
if metadata.get('update'):
|
|
||||||
query_dict['metadata%s_id' % identifier] = metadata['id']
|
|
||||||
query_dict['metadata%s_value' % identifier] = metadata['value']
|
|
||||||
except TypeError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
try:
|
|
||||||
query_dict['tags'] = ([force_text(tag.pk) for tag in self.get_cleaned_data_for_step(STEP_TAGS)['tags']])
|
|
||||||
|
|
||||||
except AttributeError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
url = '?'.join(
|
url = '?'.join(
|
||||||
[
|
[
|
||||||
|
|||||||
Reference in New Issue
Block a user