Merge branch 'feature/version_revert' into development

This commit is contained in:
Roberto Rosario
2011-12-04 02:03:38 -04:00
10 changed files with 94 additions and 70 deletions

View File

@@ -16,15 +16,15 @@ from project_setup.api import register_setup
from documents.models import (Document, DocumentPage,
DocumentPageTransformation, DocumentType, DocumentTypeFilename,
DocumentVersion)
from documents.literals import PERMISSION_DOCUMENT_CREATE, \
PERMISSION_DOCUMENT_PROPERTIES_EDIT, PERMISSION_DOCUMENT_VIEW, \
PERMISSION_DOCUMENT_DELETE, PERMISSION_DOCUMENT_DOWNLOAD, \
PERMISSION_DOCUMENT_TRANSFORM, PERMISSION_DOCUMENT_TOOLS, \
PERMISSION_DOCUMENT_EDIT
from documents.literals import PERMISSION_DOCUMENT_TYPE_EDIT, \
PERMISSION_DOCUMENT_TYPE_DELETE, PERMISSION_DOCUMENT_TYPE_CREATE
from documents.literals import HISTORY_DOCUMENT_CREATED, \
HISTORY_DOCUMENT_EDITED, HISTORY_DOCUMENT_DELETED
from documents.literals import (PERMISSION_DOCUMENT_CREATE,
PERMISSION_DOCUMENT_PROPERTIES_EDIT, PERMISSION_DOCUMENT_VIEW,
PERMISSION_DOCUMENT_DELETE, PERMISSION_DOCUMENT_DOWNLOAD,
PERMISSION_DOCUMENT_TRANSFORM, PERMISSION_DOCUMENT_TOOLS,
PERMISSION_DOCUMENT_EDIT, PERMISSION_DOCUMENT_VERSION_REVERT)
from documents.literals import (PERMISSION_DOCUMENT_TYPE_EDIT,
PERMISSION_DOCUMENT_TYPE_DELETE, PERMISSION_DOCUMENT_TYPE_CREATE)
from documents.literals import (HISTORY_DOCUMENT_CREATED,
HISTORY_DOCUMENT_EDITED, HISTORY_DOCUMENT_DELETED)
from documents.conf.settings import ZOOM_MAX_LEVEL
from documents.conf.settings import ZOOM_MIN_LEVEL
from documents.conf import settings as document_settings
@@ -46,6 +46,10 @@ def is_min_zoom(context):
def is_max_zoom(context):
return context['zoom'] >= ZOOM_MAX_LEVEL
def is_current_version(context):
return context['object'].document.latest_version.timestamp == context['object'].timestamp
# Permission setup
set_namespace_title('documents', _(u'Documents'))
register_permission(PERMISSION_DOCUMENT_CREATE)
@@ -56,6 +60,7 @@ register_permission(PERMISSION_DOCUMENT_DELETE)
register_permission(PERMISSION_DOCUMENT_DOWNLOAD)
register_permission(PERMISSION_DOCUMENT_TRANSFORM)
register_permission(PERMISSION_DOCUMENT_TOOLS)
register_permission(PERMISSION_DOCUMENT_VERSION_REVERT)
# Document type permissions
set_namespace_title('documents_setup', _(u'Documents setup'))
@@ -80,8 +85,8 @@ document_edit = {'text': _(u'edit'), 'view': 'document_edit', 'args': 'object.id
document_preview = {'text': _(u'preview'), 'class': 'fancybox', 'view': 'document_preview', 'args': 'object.id', 'famfam': 'magnifier', 'permissions': [PERMISSION_DOCUMENT_VIEW]}
document_download = {'text': _(u'download'), 'view': 'document_download', 'args': 'object.id', 'famfam': 'page_save', 'permissions': [PERMISSION_DOCUMENT_DOWNLOAD]}
document_version_download = {'text': _(u'download'), 'view': 'document_version_download', 'args': 'object.pk', 'famfam': 'page_save', 'permissions': [PERMISSION_DOCUMENT_DOWNLOAD]}
document_find_duplicates = {'text': _(u'find duplicates'), 'view': 'document_find_duplicates', 'args': 'object.id', 'famfam': 'page_refresh', 'permissions': [PERMISSION_DOCUMENT_VIEW]}
document_find_all_duplicates = {'text': _(u'find all duplicates'), 'view': 'document_find_all_duplicates', 'famfam': 'page_refresh', 'permissions': [PERMISSION_DOCUMENT_VIEW], 'description': _(u'Search all the documents\' checksums and return a list of the exact matches.')}
document_find_duplicates = {'text': _(u'find duplicates'), 'view': 'document_find_duplicates', 'args': 'object.id', 'famfam': 'page_white_copy', 'permissions': [PERMISSION_DOCUMENT_VIEW]}
document_find_all_duplicates = {'text': _(u'find all duplicates'), 'view': 'document_find_all_duplicates', 'famfam': 'page_white_copy', 'permissions': [PERMISSION_DOCUMENT_VIEW], 'description': _(u'Search all the documents\' checksums and return a list of the exact matches.')}
document_update_page_count = {'text': _(u'update office documents\' page count'), 'view': 'document_update_page_count', 'famfam': 'page_white_csharp', 'permissions': [PERMISSION_DOCUMENT_TOOLS], 'description': _(u'Update the page count of the office type documents. This is useful when enabling office document support after there were already office type documents in the database.')}
document_clear_transformations = {'text': _(u'clear transformations'), 'view': 'document_clear_transformations', 'args': 'object.id', 'famfam': 'page_paintbrush', 'permissions': [PERMISSION_DOCUMENT_TRANSFORM]}
document_multiple_clear_transformations = {'text': _(u'clear transformations'), 'view': 'document_multiple_clear_transformations', 'famfam': 'page_paintbrush', 'permissions': [PERMISSION_DOCUMENT_TRANSFORM]}
@@ -113,6 +118,7 @@ document_page_view_reset = {'text': _(u'reset view'), 'class': 'no-parent-histor
# Document versions
document_version_list = {'text': _(u'versions'), 'view': 'document_version_list', 'args': 'object.pk', 'famfam': 'page_world', 'permissions': [PERMISSION_DOCUMENT_VIEW]}
document_version_revert = {'text': _(u'revert'), 'view': 'document_version_revert', 'args': 'object.pk', 'famfam': 'page_refresh', 'permissions': [PERMISSION_DOCUMENT_VERSION_REVERT], 'conditional_disable': is_current_version}
# Document type related links
document_type_list = {'text': _(u'document type list'), 'view': 'document_type_list', 'famfam': 'layout', 'permissions': [PERMISSION_DOCUMENT_VIEW]}
@@ -141,7 +147,7 @@ register_links(Document, [document_edit, document_print, document_delete, docume
register_multi_item_links(['document_find_duplicates', 'folder_view', 'index_instance_list', 'document_type_document_list', 'search', 'results', 'document_group_view', 'document_list', 'document_list_recent'], [document_multiple_clear_transformations, document_multiple_delete])
# Document Version links
register_links(DocumentVersion, [document_version_download])
register_links(DocumentVersion, [document_version_revert, document_version_download])
secondary_menu_links = [document_list_recent, document_list, document_create_multiple]

View File

@@ -13,6 +13,7 @@ PERMISSION_DOCUMENT_DELETE = {'namespace': 'documents', 'name': 'document_delete
PERMISSION_DOCUMENT_DOWNLOAD = {'namespace': 'documents', 'name': 'document_download', 'label': _(u'Download documents')}
PERMISSION_DOCUMENT_TRANSFORM = {'namespace': 'documents', 'name': 'document_transform', 'label': _(u'Transform documents')}
PERMISSION_DOCUMENT_TOOLS = {'namespace': 'documents', 'name': 'document_tools', 'label': _(u'Execute document modifying tools')}
PERMISSION_DOCUMENT_VERSION_REVERT = {'namespace': 'documents', 'name': 'document_version_revert', 'label': _(u'Revert documents to a previous version')}
PERMISSION_DOCUMENT_TYPE_EDIT = {'namespace': 'documents_setup', 'name': 'document_type_edit', 'label': _(u'Edit document types')}
PERMISSION_DOCUMENT_TYPE_DELETE = {'namespace': 'documents_setup', 'name': 'document_type_delete', 'label': _(u'Delete document types')}

View File

@@ -78,7 +78,7 @@ class Document(models.Model):
uuid = models.CharField(max_length=48, blank=True, editable=False)
document_type = models.ForeignKey(DocumentType, verbose_name=_(u'document type'), null=True, blank=True)
description = models.TextField(blank=True, null=True, verbose_name=_(u'description'), db_index=True)
date_added = models.DateTimeField(verbose_name=_(u'added'), db_index=True)
date_added = models.DateTimeField(verbose_name=_(u'added'), db_index=True, editable=False)
tags = TaggableManager()
@@ -113,35 +113,39 @@ class Document(models.Model):
self.date_added = datetime.datetime.now()
super(Document, self).save(*args, **kwargs)
def get_cached_image_name(self, page):
document_page = self.pages.get(page_number=page)
def get_cached_image_name(self, page, version):
document_version = DocumentVersion.objects.get(pk=version)
document_page = document_version.documentpage_set.get(page_number=page)
transformations, warnings = document_page.get_transformation_list()
hash_value = HASH_FUNCTION(u''.join([self.checksum, unicode(page), unicode(transformations)]))
hash_value = HASH_FUNCTION(u''.join([document_version.checksum, unicode(page), unicode(transformations)]))
return os.path.join(CACHE_PATH, hash_value), transformations
def get_image_cache_name(self, page):
cache_file_path, transformations = self.get_cached_image_name(page)
def get_image_cache_name(self, page, version):
cache_file_path, transformations = self.get_cached_image_name(page, version)
if os.path.exists(cache_file_path):
return cache_file_path
else:
document_file = document_save_to_temp_dir(self, self.checksum)
document_version = DocumentVersion.objects.get(pk=version)
document_file = document_save_to_temp_dir(document_version, document_version.checksum)
return convert(document_file, output_filepath=cache_file_path, page=page, transformations=transformations, mimetype=self.file_mimetype)
def get_valid_image(self, size=DISPLAY_SIZE, page=DEFAULT_PAGE_NUMBER, zoom=DEFAULT_ZOOM_LEVEL, rotation=DEFAULT_ROTATION):
image_cache_name = self.get_image_cache_name(page=page)
def get_valid_image(self, size=DISPLAY_SIZE, page=DEFAULT_PAGE_NUMBER, zoom=DEFAULT_ZOOM_LEVEL, rotation=DEFAULT_ROTATION, version=None):
if not version:
version = self.latest_version.pk
image_cache_name = self.get_image_cache_name(page=page, version=version)
return convert(image_cache_name, cleanup_files=False, size=size, zoom=zoom, rotation=rotation)
def get_image(self, size=DISPLAY_SIZE, page=DEFAULT_PAGE_NUMBER, zoom=DEFAULT_ZOOM_LEVEL, rotation=DEFAULT_ROTATION, as_base64=False):
def get_image(self, size=DISPLAY_SIZE, page=DEFAULT_PAGE_NUMBER, zoom=DEFAULT_ZOOM_LEVEL, rotation=DEFAULT_ROTATION, as_base64=False, version=None):
if zoom < ZOOM_MIN_LEVEL:
zoom = ZOOM_MIN_LEVEL
if zoom > ZOOM_MAX_LEVEL:
zoom = ZOOM_MAX_LEVEL
rotation = rotation % 360
rotation = rotation % 360
try:
file_path = self.get_valid_image(size=size, page=page, zoom=zoom, rotation=rotation)
file_path = self.get_valid_image(size=size, page=page, zoom=zoom, rotation=rotation, version=version)
except UnknownFileFormat:
file_path = get_icon_file_path(self.file_mimetype)
except UnkownConvertError:
@@ -184,6 +188,7 @@ class Document(models.Model):
logger.debug('creating new document version')
if version_update:
new_version_dict = self.latest_version.get_new_version_dict(version_update)
logger.debug('new_version_dict: %s' % new_version_dict)
new_version = DocumentVersion(
document=self,
file=file,
@@ -203,9 +208,6 @@ class Document(models.Model):
)
new_version.save()
logger.debug('new_version_dict: %s' % new_version_dict)
logger.debug('new_version saved')
return new_version
@@ -438,6 +440,13 @@ class DocumentVersion(models.Model):
page_transformation.save()
def revert(self):
'''
Delete the subsequent versions after this one
'''
for version in self.document.versions.filter(timestamp__gt=self.timestamp):
version.delete()
def update_mimetype(self, save=True):
'''
Read a document verions's file and determine the mimetype by calling the
@@ -454,7 +463,7 @@ class DocumentVersion(models.Model):
self.save()
def delete(self, *args, **kwargs):
super(Document, self).delete(*args, **kwargs)
super(DocumentVersion, self).delete(*args, **kwargs)
return self.file.storage.delete(self.file.path)
def exists(self):

Binary file not shown.

After

Width:  |  Height:  |  Size: 862 B

View File

@@ -36,6 +36,7 @@ urlpatterns = patterns('documents.views',
url(r'^(?P<document_pk>\d+)/version/all/$', 'document_version_list', (), 'document_version_list'),
url(r'^document/version/(?P<document_version_pk>\d+)/download/$', 'document_download', (), 'document_version_download'),
url(r'^document/version/(?P<document_version_pk>\d+)/revert/$', 'document_version_revert', (), 'document_version_revert'),
url(r'^multiple/clear_transformations/$', 'document_multiple_clear_transformations', (), 'document_multiple_clear_transformations'),
url(r'^duplicates/list/$', 'document_find_all_duplicates', (), 'document_find_all_duplicates'),

View File

@@ -36,14 +36,15 @@ from documents.conf.settings import ROTATION_STEP
from documents.conf.settings import PRINT_SIZE
from documents.conf.settings import RECENT_COUNT
from documents.literals import PERMISSION_DOCUMENT_CREATE, \
PERMISSION_DOCUMENT_PROPERTIES_EDIT, \
PERMISSION_DOCUMENT_VIEW, \
PERMISSION_DOCUMENT_DELETE, PERMISSION_DOCUMENT_DOWNLOAD, \
PERMISSION_DOCUMENT_TRANSFORM, \
PERMISSION_DOCUMENT_EDIT, PERMISSION_DOCUMENT_TOOLS
from documents.literals import HISTORY_DOCUMENT_CREATED, \
HISTORY_DOCUMENT_EDITED, HISTORY_DOCUMENT_DELETED
from documents.literals import (PERMISSION_DOCUMENT_CREATE,
PERMISSION_DOCUMENT_PROPERTIES_EDIT,
PERMISSION_DOCUMENT_VIEW,
PERMISSION_DOCUMENT_DELETE, PERMISSION_DOCUMENT_DOWNLOAD,
PERMISSION_DOCUMENT_TRANSFORM,
PERMISSION_DOCUMENT_EDIT, PERMISSION_DOCUMENT_TOOLS,
PERMISSION_DOCUMENT_VERSION_REVERT)
from documents.literals import (HISTORY_DOCUMENT_CREATED,
HISTORY_DOCUMENT_EDITED, HISTORY_DOCUMENT_DELETED)
from documents.forms import (DocumentTypeSelectForm,
DocumentForm_edit, DocumentPropertiesForm,
@@ -279,6 +280,8 @@ def get_document_image(request, document_id, size=PREVIEW_SIZE, base64_version=F
page = int(request.GET.get('page', DEFAULT_PAGE_NUMBER))
zoom = int(request.GET.get('zoom', DEFAULT_ZOOM_LEVEL))
version = int(request.GET.get('version', document.latest_version.pk))
if zoom < ZOOM_MIN_LEVEL:
zoom = ZOOM_MIN_LEVEL
@@ -289,10 +292,10 @@ def get_document_image(request, document_id, size=PREVIEW_SIZE, base64_version=F
rotation = int(request.GET.get('rotation', DEFAULT_ROTATION)) % 360
if base64_version:
return HttpResponse(u'<html><body><img src="%s" /></body></html>' % document.get_image(size=size, page=page, zoom=zoom, rotation=rotation, as_base64=True))
return HttpResponse(u'<html><body><img src="%s" /></body></html>' % document.get_image(size=size, page=page, zoom=zoom, rotation=rotation, as_base64=True, version=version))
else:
# TODO: fix hardcoded MIMETYPE
return sendfile.sendfile(request, document.get_image(size=size, page=page, zoom=zoom, rotation=rotation), mimetype=DEFAULT_FILE_FORMAT_MIMETYPE)
return sendfile.sendfile(request, document.get_image(size=size, page=page, zoom=zoom, rotation=rotation, version=version), mimetype=DEFAULT_FILE_FORMAT_MIMETYPE)
def document_download(request, document_id=None, document_version_pk=None):
@@ -1188,3 +1191,26 @@ def document_version_list(request, document_pk):
return render_to_response('generic_list.html', context,
context_instance=RequestContext(request))
def document_version_revert(request, document_version_pk):
check_permissions(request.user, [PERMISSION_DOCUMENT_VERSION_REVERT])
previous = request.POST.get('previous', request.GET.get('previous', request.META.get('HTTP_REFERER', '/')))
if request.method == 'POST':
try:
document_version = get_object_or_404(DocumentVersion, pk=document_version_pk)
document_version.revert()
messages.success(request, _(u'Document version reverted successfully'))
except Exception, msg:
messages.error(request, _(u'Error reverting document version; %s') % msg)
return HttpResponseRedirect(previous)
return render_to_response('generic_confirm.html', {
'previous': previous,
'title': _(u'Are you sure you wish to revert to this version?'),
'message': _(u'All later version after this one will be deleted too.'),
'form_icon': u'page_refresh.png',
}, context_instance=RequestContext(request))

View File

@@ -20,14 +20,19 @@ def document_link(document):
return mark_safe(u'<a href="%s">%s</a>' % (reverse('document_view_simple', args=[document.pk]), document))
def document_html_widget(document, view='document_thumbnail', click_view=None, page=DEFAULT_PAGE_NUMBER, zoom=DEFAULT_ZOOM_LEVEL, rotation=DEFAULT_ROTATION, gallery_name=None, fancybox_class='fancybox'):
def document_html_widget(document, view='document_thumbnail', click_view=None, page=DEFAULT_PAGE_NUMBER, zoom=DEFAULT_ZOOM_LEVEL, rotation=DEFAULT_ROTATION, gallery_name=None, fancybox_class='fancybox', version=None):
result = []
alt_text = _(u'document page image')
if not version:
version = document.latest_version.pk
query_dict = {
'page': page,
'zoom': zoom,
'rotation': rotation,
'version': version,
}
if gallery_name:
@@ -67,7 +72,7 @@ def document_html_widget(document, view='document_thumbnail', click_view=None, p
});
</script>
''' % {
'url': reverse('documents-expensive-is_zoomable', args=[document.pk, page]),
'url': reverse('documents-expensive-is_zoomable', args=[document.pk, version, page]),
'pk': document.pk,
'page': page if page else 1,
'plain_template': mark_safe(u''.join(plain_template)),

View File

@@ -40,30 +40,6 @@ class DocumentResourceSimple(ModelResource):
}
for version in instance.versions.all()
]
'''
return [
{
'version': 1,
'mimetype': instance.file_mimetype,
'encoding': instance.file_mime_encoding,
'filename': instance.filename,
'date_updated': instance.date_updated,
'checksum': instance.checksum,
'size': instance.size,
'exists': instance.exists(),
'pages': [
{
'page_numer': page.page_number,
'page_label': page.page_label,
'is_zoomable': reverse('documents-expensive-is_zoomable', args=[instance.pk, page.page_number]),
#'content':
}
for page in instance.documentpage_set.all()
]
}
]
'''
def expensive_methods(self, instance):
return []

View File

@@ -12,5 +12,5 @@ urlpatterns = patterns('',
# Version 0 alpha API calls
url(r'^v0/document/(?P<pk>[0-9]+)/$', ReadOnlyInstanceModelView.as_view(resource=DocumentResourceSimple), name='documents-simple'),
url(r'^v0/document/(?P<pk>[0-9]+)/page/(?P<page_number>[0-9]+)/expensive/is_zoomable/$', IsZoomable.as_view(), name='documents-expensive-is_zoomable'),
url(r'^v0/document/(?P<pk>[0-9]+)/version/(?P<version_pk>[0-9]+)/page/(?P<page_number>[0-9]+)/expensive/is_zoomable/$', IsZoomable.as_view(), name='documents-expensive-is_zoomable'),
)

View File

@@ -6,7 +6,7 @@ from django.utils.translation import ugettext_lazy as _
from django.shortcuts import get_object_or_404
from django.core.urlresolvers import reverse
from documents.models import Document
from documents.models import Document, DocumentVersion
from converter.exceptions import UnknownFileFormat, UnkownConvertError
from djangorestframework.views import View, ModelView, ListModelView, InstanceModelView
@@ -45,11 +45,11 @@ class Version_0(View):
class IsZoomable(View):
def get(self, request, pk, page_number):
def get(self, request, pk, page_number, version_pk):
logger.info('received is_zoomable call from: %s' % (request.META['REMOTE_ADDR']))
document = get_object_or_404(Document, pk=pk)
document_version = get_object_or_404(DocumentVersion, pk=version_pk)
try:
document.get_image_cache_name(int(page_number))
document_version.document.get_image_cache_name(int(page_number), version_pk)
return {'result': True}
except (UnknownFileFormat, UnkownConvertError):
return {'result': False}