Files
mayan-edms/mayan/apps/sources/wizards.py
2018-04-01 20:30:10 -04:00

228 lines
6.5 KiB
Python

from __future__ import unicode_literals
from django.contrib import messages
from django.http import HttpResponseRedirect
from django.urls import reverse
from django.utils.decorators import classonlymethod
from django.utils.encoding import force_text
from django.utils.http import urlencode
from django.utils.translation import ugettext_lazy as _
from formtools.wizard.views import SessionWizardView
from common.mixins import ViewPermissionCheckMixin
from documents.forms import DocumentTypeSelectForm
from metadata.forms import DocumentMetadataFormSet
from tags.forms import TagMultipleSelectionForm
from tags.models import Tag
from .models import InteractiveSource
class WizardStep(object):
_registry = {}
@classmethod
def done(cls, wizard):
return {}
@classmethod
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):
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):
if not InteractiveSource.objects.filter(enabled=True).exists():
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(
DocumentCreateWizard, self
).dispatch(request, *args, **kwargs)
def get_context_data(self, form, **kwargs):
context = super(
DocumentCreateWizard, self
).get_context_data(form=form, **kwargs)
wizard_step = WizardStep.get(name=self.steps.current)
context.update({
'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_icon': 'fa fa-arrow-right',
'title': _('Document upload wizard'),
})
return context
def get_form_initial(self, step):
return WizardStep.get(name=step).get_form_initial(wizard=self) or {}
def get_form_kwargs(self, step):
return WizardStep.get(name=step).get_form_kwargs(wizard=self) or {}
def done(self, form_list, **kwargs):
query_dict = {}
for step in WizardStep.get_all():
query_dict.update(step.done(wizard=self) or {})
url = '?'.join(
[
reverse('sources:upload_interactive'),
urlencode(query_dict, doseq=True)
]
)
return HttpResponseRedirect(url)