293 lines
10 KiB
Python
293 lines
10 KiB
Python
# -*- coding: utf-8 -*-
|
|
|
|
# File upload related imports
|
|
import os
|
|
from django.core.files.storage import default_storage
|
|
from django.core.files.base import ContentFile
|
|
from django.conf import settings
|
|
|
|
from django.views.generic import TemplateView, FormView, CreateView, UpdateView
|
|
from django.views.generic.detail import SingleObjectMixin
|
|
from django.contrib.auth.decorators import login_required
|
|
from django.utils.decorators import method_decorator
|
|
from django.contrib.auth.views import login, logout
|
|
|
|
from django.core.urlresolvers import reverse
|
|
|
|
from frontend.forms import NewProjectForm, FileUploadForm, PersonMapForm
|
|
|
|
from frontend.models import Project
|
|
|
|
FRONTEND_PAGE_NAME = u'Citavi Mapper'
|
|
|
|
from service.Mapper import person_mapper
|
|
|
|
|
|
# Login wrapper functions
|
|
def login_wrap(*args, **kwargs):
|
|
""" Wrapper function for login page. """
|
|
kwargs[u'extra_context'] = {
|
|
u'page': {
|
|
u'name': FRONTEND_PAGE_NAME,
|
|
u'title': 'Login'
|
|
}
|
|
}
|
|
return login(*args, **kwargs)
|
|
|
|
def logout_wrap(*args, **kwargs):
|
|
""" Wrapper function for logout page. """
|
|
kwargs[u'extra_context'] = {
|
|
u'page': {
|
|
u'name': FRONTEND_PAGE_NAME,
|
|
u'title': 'Logout'
|
|
}
|
|
}
|
|
return logout(*args, **kwargs)
|
|
|
|
|
|
# My base classes for views
|
|
class MyViewMixin(object):
|
|
""" Basic view mixin to add global variables to all templates. """
|
|
template_name = u'base.html'
|
|
page_name = FRONTEND_PAGE_NAME
|
|
page_title = u'BASE'
|
|
|
|
def get_page_data(self):
|
|
return {
|
|
u'name': self.page_name,
|
|
u'title': self.page_title
|
|
}
|
|
|
|
def get_context_data(self, **kwargs):
|
|
kwargs[u'page'] = self.get_page_data()
|
|
return super(MyViewMixin, self).get_context_data(**kwargs)
|
|
|
|
class MyTemplateView(MyViewMixin, TemplateView):
|
|
pass
|
|
|
|
class MyFormView(MyViewMixin, FormView):
|
|
pass
|
|
|
|
class MyCreateView(MyViewMixin, CreateView):
|
|
pass
|
|
|
|
class MyUpdateView(MyViewMixin, UpdateView):
|
|
pass
|
|
|
|
|
|
# Mixin to protect pages
|
|
class LoggedInMixin(object):
|
|
""" Mixin to force a valid login for protected pages. """
|
|
@method_decorator(login_required)
|
|
def dispatch(self, *args, **kwargs):
|
|
return super(LoggedInMixin, self).dispatch(*args, **kwargs)
|
|
|
|
|
|
# My protected view classes
|
|
class ProtectedTemplateView(LoggedInMixin, MyTemplateView):
|
|
pass
|
|
|
|
class ProtectedFormView(LoggedInMixin, MyFormView):
|
|
pass
|
|
|
|
class ProtectedCreateView(LoggedInMixin, MyCreateView):
|
|
pass
|
|
|
|
class ProtectedUpdateView(LoggedInMixin, MyUpdateView):
|
|
pass
|
|
|
|
|
|
# Actual Views
|
|
class IndexView(ProtectedTemplateView):
|
|
template_name = u'index.html'
|
|
page_title = u'Index'
|
|
|
|
|
|
class ProjectView(ProtectedFormView):
|
|
template_name = u'projects.html'
|
|
page_title = u'Projects'
|
|
form_class = NewProjectForm
|
|
success_url = u'/project'
|
|
|
|
def get_context_data(self, **kwargs):
|
|
kwargs[u'projects'] = Project.objects.order_by(u'id')
|
|
return super(ProjectView, self).get_context_data(**kwargs)
|
|
|
|
def form_valid(self, form):
|
|
form.save()
|
|
return super(ProjectView, self).form_valid(form)
|
|
|
|
|
|
class ProjectUpdateView(ProtectedFormView, SingleObjectMixin):
|
|
template_name = u'project/update.html'
|
|
page_title = u'Update project'
|
|
form_class = FileUploadForm
|
|
|
|
success_url = u'/project/'
|
|
|
|
def get(self, request, *args, **kwargs):
|
|
self.project_id = kwargs[u'project_id']
|
|
self.object = Project.objects.get(pk=self.project_id)
|
|
return super(ProjectUpdateView, self).get(request, *args, **kwargs)
|
|
|
|
def post(self, request, *args, **kwargs):
|
|
self.project_id = kwargs[u'project_id']
|
|
self.object = Project.objects.get(pk=self.project_id)
|
|
self.success_url = self.success_url + self.project_id + u'/update'
|
|
return super(ProjectUpdateView, self).post(request, *args, **kwargs)
|
|
|
|
def form_valid(self, form, *args, **kwargs):
|
|
""" This form_valid handles the file upload. """
|
|
original_file = form.files[u'file']
|
|
original_filename = unicode(original_file)
|
|
original_contentfile = ContentFile(original_file.read())
|
|
""" Put file into temporary folder for analysis """
|
|
target_filename = u'tmp/project_' + unicode(self.project_id) + u'.ctt4'
|
|
relative_path = default_storage.save(target_filename, original_contentfile)
|
|
temp_sqlite = os.path.join(settings.MEDIA_ROOT, relative_path)
|
|
|
|
""" Test if SQLite is a valid citavi project. """
|
|
from service import Citavi
|
|
citavi_project = Citavi.Project(temp_sqlite)
|
|
citavi_project.open()
|
|
citavi_project_valid = citavi_project.is_valid()
|
|
""" Free temporary ressources. """
|
|
del citavi_project
|
|
default_storage.delete(temp_sqlite)
|
|
|
|
if citavi_project_valid == False:
|
|
""" TODO: Put up an error message or something. """
|
|
pass
|
|
else:
|
|
target_filename = u'citavi/project_' + unicode(self.project_id) + u'.ctt4'
|
|
""" Remove eventually pre-existing citavi file. """
|
|
if default_storage.exists(target_filename):
|
|
default_storage.delete(target_filename)
|
|
|
|
""" Actually store file in citavi folder """
|
|
relative_path = default_storage.save(target_filename, original_contentfile)
|
|
sqlite_path = os.path.join(settings.MEDIA_ROOT, relative_path)
|
|
|
|
""" Store new original filename in Project """
|
|
project = Project.objects.get(id=self.project_id)
|
|
project.associated_filename = original_filename
|
|
project.save()
|
|
|
|
""" Refresh identities from citavi project. """
|
|
# TODO
|
|
# citavi_project = Citavi.Project(sqlite_path)
|
|
# citavi_project.open()
|
|
# del citavi_project
|
|
return super(ProjectUpdateView, self).form_valid(form)
|
|
|
|
|
|
class ProjectPersonView(ProtectedFormView, SingleObjectMixin):
|
|
template_name = u'project/view-person.html'
|
|
page_title = u'Person List View'
|
|
form_class = FileUploadForm
|
|
|
|
success_url = u'/project/'
|
|
|
|
def get_context_data(self, **kwargs):
|
|
project = self.object
|
|
kwargs[u'unmapped_persons'] = person_mapper.get_unmapped_identities(project)
|
|
kwargs[u'mapped_persons'] = person_mapper.get_mapped_identities(project)
|
|
return super(ProjectPersonView, self).get_context_data(**kwargs)
|
|
|
|
def get(self, request, *args, **kwargs):
|
|
self.project_id = kwargs[u'project_id']
|
|
self.object = Project.objects.get(pk=self.project_id)
|
|
return super(ProjectPersonView, self).get(request, *args, **kwargs)
|
|
|
|
def post(self, request, *args, **kwargs):
|
|
self.project_id = kwargs[u'project_id']
|
|
# self.success_url = self.success_url + self.project_id + '/update'
|
|
return super(ProjectPersonView, self).post(request, *args, **kwargs)
|
|
|
|
def form_valid(self, form, *args, **kwargs):
|
|
return super(ProjectPersonView, self).form_valid(form)
|
|
|
|
|
|
class ProjectMapPersonView(ProtectedFormView, SingleObjectMixin):
|
|
""" View containing the person mapping 'wizard'. """
|
|
template_name = u'project/map-person.html'
|
|
page_title = u'Person Mapping'
|
|
form_class = PersonMapForm
|
|
|
|
success_url = u'/project'
|
|
|
|
_unmapped_persons = None
|
|
|
|
def _refresh_unmapped(self):
|
|
""" Refresh data about unmapped persons. """
|
|
self._unmapped_persons = person_mapper.get_unmapped_identities(self.object)
|
|
|
|
def _is_unmapped(self, person_uuid):
|
|
""" Returns True if the given person is not mapped yet. """
|
|
if not self._unmapped_persons:
|
|
self._refresh_unmapped()
|
|
return person_uuid in self._unmapped_persons
|
|
|
|
def get_context_data(self, **kwargs):
|
|
project = self.object
|
|
kwargs[u'person'] = person_mapper.get_person_by_uuid(project, self.person_uuid)
|
|
return super(ProjectMapPersonView, self).get_context_data(**kwargs)
|
|
|
|
def get_success_url(self):
|
|
""" TODO: Make this work! - Update success uri to next unmapped person. """
|
|
last_uuid = unicode(self.person_uuid)
|
|
self._refresh_unmapped()
|
|
unmapped = self._unmapped_persons.items()
|
|
first_person_uuid = unmapped[0][0]
|
|
next_uuid = first_person_uuid
|
|
unmapped.reverse()
|
|
|
|
while True:
|
|
try:
|
|
current_person = unmapped.pop()
|
|
if current_person[1].ID == last_uuid:
|
|
next_uuid = unmapped.pop()[0]
|
|
break
|
|
except IndexError:
|
|
break
|
|
|
|
kwargs = {
|
|
u"project_id": self.object.id,
|
|
u"person_uuid": next_uuid
|
|
}
|
|
return reverse('frontend-project-map-person', kwargs=kwargs)
|
|
|
|
def get(self, request, *args, **kwargs):
|
|
self.project_id = kwargs[u'project_id']
|
|
self.person_uuid = kwargs[u'person_uuid']
|
|
self.object = Project.objects.get(pk=self.project_id)
|
|
if self._is_unmapped(self.person_uuid) == False:
|
|
raise Exception("Sorry, this person was already mapped. Try deleting the existing mapping and move on. TODO: Make this more beautiful.")
|
|
self._refresh_unmapped()
|
|
return super(ProjectMapPersonView, self).get(request, *args, **kwargs)
|
|
|
|
def post(self, request, *args, **kwargs):
|
|
self.project_id = kwargs[u'project_id']
|
|
self.person_uuid = kwargs[u'person_uuid']
|
|
self.object = Project.objects.get(pk=self.project_id)
|
|
if self._is_unmapped(self.person_uuid) == False:
|
|
raise Exception("Sorry, this person was already mapped. Try deleting the existing mapping and move on. TODO: Make this more beautiful.")
|
|
self._refresh_unmapped()
|
|
return super(ProjectMapPersonView, self).post(request, *args, **kwargs)
|
|
|
|
def form_valid(self, form, *args, **kwargs):
|
|
person = person_mapper.get_person_by_uuid(self.object, self.person_uuid)
|
|
|
|
if form.data.get(u'skip', False):
|
|
""" Nothing to do here, just go on ... """
|
|
pass
|
|
elif form.data.get(u'save-continue', False):
|
|
# TODO: do mapping according to parameters, override success_url to point to next person!
|
|
if form.cleaned_data[u'action'] == u'new':
|
|
person_mapper.create_new_identity(self.object, person)
|
|
elif form.cleaned_data[u'action'] == u'existing':
|
|
global_identity = form.cleaned_data[u'global_identity']
|
|
person_mapper.map_identity_to_existing(global_identity, self.object, person.ID, form.cleaned_data[u'preferred_identity'])
|
|
return super(ProjectMapPersonView, self).form_valid(form)
|
|
|