diff --git a/mayan/apps/converter/transformations.py b/mayan/apps/converter/transformations.py index 0e86129938..fd3e822d92 100644 --- a/mayan/apps/converter/transformations.py +++ b/mayan/apps/converter/transformations.py @@ -265,22 +265,22 @@ class TransformationDrawRectanglePercent(BaseTransformation): super(TransformationDrawRectanglePercent, self).execute_on(*args, **kwargs) try: - left = int(self.left or '0') + left = float(self.left or '0') except ValueError: left = 0 try: - top = int(self.top or '0') + top = float(self.top or '0') except ValueError: top = 0 try: - right = int(self.right or '0') + right = float(self.right or '0') except ValueError: right = 0 try: - bottom = int(self.bottom or '0') + bottom = float(self.bottom or '0') except ValueError: bottom = 0 @@ -308,11 +308,11 @@ class TransformationDrawRectanglePercent(BaseTransformation): if bottom > 100: bottom = 100 - if left > right: - left, right = right, left + #if left > right: + # left, right = right, left - if top > bottom: - top, bottom = bottom, top + #if top > bottom: + # top, bottom = bottom, top logger.debug( 'left: %f, top: %f, right: %f, bottom: %f', left, top, right, diff --git a/mayan/apps/redactions/admin.py b/mayan/apps/redactions/admin.py deleted file mode 100644 index 155a865758..0000000000 --- a/mayan/apps/redactions/admin.py +++ /dev/null @@ -1,15 +0,0 @@ -from __future__ import unicode_literals - -from django.contrib import admin - -#from .models import OCRZone, OCRZoneContent - - -#@admin.register(OCRZone) -#class OCRZoneAdmin(admin.ModelAdmin): -# list_display = ('document_type', 'label', 'slug', 'enabled') -# list_display_links = ('label', 'slug') -# prepopulated_fields = {'slug': ('label',)} - - -#admin.site.register(OCRZoneContent) diff --git a/mayan/apps/redactions/apps.py b/mayan/apps/redactions/apps.py index 64ba7aa9cb..45409d76db 100644 --- a/mayan/apps/redactions/apps.py +++ b/mayan/apps/redactions/apps.py @@ -3,20 +3,16 @@ from __future__ import unicode_literals import logging from django.apps import apps -from django.db.models.signals import post_save from django.utils.translation import ugettext_lazy as _ -from mayan.apps.acls.classes import ModelPermission from mayan.apps.common.apps import MayanAppConfig from mayan.apps.common.menus import ( - menu_facet, menu_list_facet, menu_multi_item, menu_object, menu_secondary, - menu_tools + menu_list_facet, menu_object, menu_secondary, ) -from mayan.apps.navigation.classes import SourceColumn -from .handlers import handler_create_default_full_zone from .links import ( - link_redaction_create, link_redaction_edit, link_redaction_list + link_redaction_create, link_redaction_delete, link_redaction_edit, + link_redaction_list ) logger = logging.getLogger(__name__) @@ -33,19 +29,10 @@ class RedactionsApp(MayanAppConfig): def ready(self): super(RedactionsApp, self).ready() - Document = apps.get_model( - app_label='documents', model_name='Document' - ) DocumentPage = apps.get_model( app_label='documents', model_name='DocumentPage' ) Redaction = self.get_model(model_name='Redaction') - Transformation = apps.get_model( - app_label='converter', model_name='Transformation' - ) - - #columns = SourceColumn.get_for_source(context=None, source=Transformation) - #print("@@@", columns) menu_list_facet.bind_links( links=( @@ -53,7 +40,8 @@ class RedactionsApp(MayanAppConfig): ), sources=(DocumentPage,) ) menu_object.bind_links( - links=(link_redaction_edit,), sources=(Transformation,) + links=(link_redaction_delete, link_redaction_edit,), + sources=(Redaction,) ) menu_secondary.bind_links( links=(link_redaction_create,), sources=(Redaction,) diff --git a/mayan/apps/redactions/forms.py b/mayan/apps/redactions/forms.py index e19d4aad7d..cd773fae29 100644 --- a/mayan/apps/redactions/forms.py +++ b/mayan/apps/redactions/forms.py @@ -1,44 +1,15 @@ from __future__ import unicode_literals -import base64 - -from PIL import Image - from django import forms -from django.utils.encoding import force_unicode -from django.utils.html import conditional_escape -from django.utils.safestring import mark_safe from django.utils.translation import ugettext_lazy as _ -from mayan.apps.common.widgets import TextAreaDiv -from mayan.apps.converter.models import Transformation -#from metadata.models import MetadataType - from .models import Redaction -class RedactionForm(forms.ModelForm): - def __init__(self, *args, **kwargs): - self.document_page = kwargs.pop('document_page', None) - super(RedactionForm, self).__init__(*args, **kwargs) - #if not self.document_type and self.instance: - # self.document_type = self.instance.document_type - - class Meta: - #fields = ('label', 'slug', 'enabled') - fields = () - model = Redaction - - class RedactionCoordinatesForm(forms.ModelForm): class Meta: - #fields = ('label', 'slug', 'enabled', 'top', 'left', 'right', 'bottom') - #fields = ('top', 'left', 'right', 'bottom') fields = ('arguments',) model = Redaction widgets = { - #'top': forms.widgets.HiddenInput, - #'left': forms.widgets.HiddenInput, - #'right': forms.widgets.HiddenInput, - #'bottom': forms.widgets.HiddenInput, + 'arguments': forms.widgets.Textarea(attrs={'class': 'hidden'}), } diff --git a/mayan/apps/redactions/icons.py b/mayan/apps/redactions/icons.py index 6b1020fcfa..8c740887e3 100644 --- a/mayan/apps/redactions/icons.py +++ b/mayan/apps/redactions/icons.py @@ -6,4 +6,6 @@ icon_redaction_create = Icon( driver_name='fontawesome-dual', primary_symbol='highlighter', secondary_symbol='plus' ) +icon_redaction_delete = Icon(driver_name='fontawesome', symbol='times') +icon_redaction_edit = Icon(driver_name='fontawesome', symbol='pencil-alt') icon_redactions = Icon(driver_name='fontawesome', symbol='highlighter') diff --git a/mayan/apps/redactions/links.py b/mayan/apps/redactions/links.py index 5c0bfd68e0..90eb51ec59 100644 --- a/mayan/apps/redactions/links.py +++ b/mayan/apps/redactions/links.py @@ -4,22 +4,29 @@ from django.utils.translation import ugettext_lazy as _ from mayan.apps.navigation.classes import Link +from .permissions import ( + permission_redaction_create, permission_redaction_delete, + permission_redaction_edit, permission_redaction_view +) + link_redaction_create = Link( icon_class_path='mayan.apps.redactions.icons.icon_redaction_create', - #permissions=(,), text=_('Redactions'), - text=_('Add redaction'), + permissions=(permission_redaction_create,), text=_('Create redaction'), view='redactions:redaction_create', args='resolved_object.id' ) +link_redaction_delete = Link( + icon_class_path='mayan.apps.redactions.icons.icon_redaction_delete', + permissions=(permission_redaction_delete,), tags='dangerous', + text=_('Delete'), view='redactions:redaction_delete', + args='resolved_object.id' +) link_redaction_edit = Link( - #icon_class_path='mayan.apps.redactions.icons.icon_redaction_create', - #permissions=(,), text=_('Redactions'), - text=_('Edit'), + icon_class_path='mayan.apps.redactions.icons.icon_redaction_edit', + permissions=(permission_redaction_edit,), text=_('Edit'), view='redactions:redaction_edit', args='resolved_object.id' ) link_redaction_list = Link( icon_class_path='mayan.apps.redactions.icons.icon_redactions', - #permissions=(,), text=_('Redactions'), - text=_('Redactions'), + permissions=(permission_redaction_view,), text=_('Redactions'), view='redactions:redaction_list', args='resolved_object.id' ) - diff --git a/mayan/apps/redactions/literals.py b/mayan/apps/redactions/literals.py deleted file mode 100644 index be9cb09cc6..0000000000 --- a/mayan/apps/redactions/literals.py +++ /dev/null @@ -1,7 +0,0 @@ -#from __future__ import unicode_literals -# -#DEFAULT_OCR_FILE_FORMAT = 'tiff' -#DEFAULT_OCR_FILE_EXTENSION = 'tif' -#DEFAULT_OCR_TASK_RETRY_DELAY = 10 -#LOCK_EXPIRE = 60 * 10 # Adjust to worst case scenario -#UNPAPER_FILE_FORMAT = 'ppm' diff --git a/mayan/apps/redactions/models.py b/mayan/apps/redactions/models.py index 06af3f4c20..1ae9d7c00b 100644 --- a/mayan/apps/redactions/models.py +++ b/mayan/apps/redactions/models.py @@ -1,10 +1,5 @@ from __future__ import unicode_literals -import io - -from django.core.exceptions import ValidationError, NON_FIELD_ERRORS -from django.db import models -from django.utils.encoding import python_2_unicode_compatible from django.utils.translation import ugettext_lazy as _ from mayan.apps.converter.models import Transformation diff --git a/mayan/apps/redactions/parsers/__init__.py b/mayan/apps/redactions/parsers/__init__.py deleted file mode 100644 index bfaf93644f..0000000000 --- a/mayan/apps/redactions/parsers/__init__.py +++ /dev/null @@ -1,178 +0,0 @@ -from __future__ import unicode_literals - -import logging -import os -#import slate -import subprocess -import tempfile - -from django.utils.translation import ugettext_lazy as _ - -from common.settings import setting_temporary_directory -from common.utils import copyfile -from converter.exceptions import OfficeConversionError -from converter.classes import ( - CONVERTER_OFFICE_FILE_MIMETYPES -) - -from ..settings import setting_pdftotext_path - -from .exceptions import ParserError, ParserUnknownFile - - -mimetype_registry = {} -logger = logging.getLogger(__name__) - - -def register_parser(mimetypes, parsers): - for mimetype in mimetypes: - for parser in parsers: - try: - parser_instance = parser() - except ParserError: - # If parser fails initialization is not added to the list for this mimetype - pass - else: - mimetype_registry.setdefault(mimetype, []).append(parser_instance) - - -def parse_document_page(document_page, descriptor=None, mimetype=None): - logger.debug('executing') - logger.debug('document_page: %s', document_page) - logger.debug('document mimetype: %s', document_page.document.file_mimetype) - - if not mimetype: - mimetype = document_page.document.file_mimetype - if mimetype.startswith('text/'): - if mimetype not in CONVERTER_OFFICE_FILE_MIMETYPES: - mimetype = 'text/plain' - logger.debug('fallback to mimetype text/plain') - logger.debug('used mimetype: %s', mimetype) - - try: - for parser in mimetype_registry[mimetype]: - try: - parser.parse(document_page, descriptor) - except ParserError: - # If parser raises error, try next parser in the list - pass - else: - # If parser was successfull there is no need to try - # others in the list for this mimetype - return - - raise ParserError('Parser list exhausted') - except KeyError: - raise ParserUnknownFile - - -class Parser(object): - """ - Parser base class - """ - - def parse(self, document_page, descriptor=None): - raise NotImplementedError('Your %s class has not defined a parse() method, which is required.', self.__class__.__name__) - - -class SlateParser(Parser): - """ - Parser for PDF files using the slate library for Python - """ - def parse(self, document_page, descriptor=None): - logger.debug('Starting SlateParser') - - if not descriptor: - descriptor = document_page.document_version.open() - - pdf_pages = slate.PDF(descriptor) - descriptor.close() - - if pdf_pages[document_page.page_number - 1] == b'\x0c': - logger.debug('The Slate parser didn\'t return any output') - raise ParserError('No output') - - document_page.content = pdf_pages[document_page.page_number - 1] - document_page.page_label = _('Text extracted from PDF') - document_page.save() - - -class OfficeParser(Parser): - """ - Parser for office document formats - """ - def parse(self, document_page, descriptor=None): - logger.debug('executing') - try: - office_converter = OfficeConverter() - document_file = document_page.document.document_save_to_temp_dir(document_page.document.checksum) - logger.debug('document_file: %s', document_file) - - office_converter.convert(document_file, mimetype=document_page.document.file_mimetype) - if office_converter.exists: - input_filepath = office_converter.output_filepath - logger.debug('office_converter.output_filepath: %s', input_filepath) - - # Now that the office document has been converted to PDF - # call the coresponding PDF parser in this new file - parse_document_page(document_page, descriptor=open(input_filepath), mimetype='application/pdf') - else: - raise ParserError - - except OfficeConversionError as exception: - logger.error(exception) - raise ParserError - - -class PopplerParser(Parser): - """ - PDF parser using the pdftotext execute from the poppler package - """ - def __init__(self): - self.pdftotext_path = setting_pdftotext_path.value if setting_pdftotext_path.value else '/usr/bin/pdftotext' - if not os.path.exists(self.pdftotext_path): - raise ParserError('cannot find pdftotext executable') - logger.debug('self.pdftotext_path: %s', self.pdftotext_path) - - def parse(self, document_page, descriptor=None): - logger.debug('parsing PDF with PopplerParser') - pagenum = str(document_page.page_number) - - if descriptor: - destination_descriptor, temp_filepath = tempfile.mkstemp(dir=setting_temporary_directory.value) - copyfile(descriptor, temp_filepath) - document_file = temp_filepath - else: - document_file = document_page.document.document_save_to_temp_dir(document_page.document.checksum) - - logger.debug('document_file: %s', document_file) - - logger.debug('parsing PDF page %s', pagenum) - - command = [] - command.append(self.pdftotext_path) - command.append('-f') - command.append(pagenum) - command.append('-l') - command.append(pagenum) - command.append(document_file) - command.append('-') - - proc = subprocess.Popen(command, close_fds=True, stderr=subprocess.PIPE, stdout=subprocess.PIPE) - return_code = proc.wait() - if return_code != 0: - logger.error(proc.stderr.readline()) - raise ParserError - - output = proc.stdout.read() - if output == b'\x0c': - logger.debug('Parser didn\'t return any output') - raise ParserError('No output') - - document_page.content = output - document_page.page_label = _('Text extracted from PDF') - document_page.save() - - -#register_parser(mimetypes=['application/pdf'], parsers=[PopplerParser, SlateParser]) -# register_parser(mimetypes=office_converter.CONVERTER_OFFICE_FILE_MIMETYPES, parsers=[OfficeParser]) # TODO: FIX diff --git a/mayan/apps/redactions/parsers/exceptions.py b/mayan/apps/redactions/parsers/exceptions.py deleted file mode 100644 index e06875f222..0000000000 --- a/mayan/apps/redactions/parsers/exceptions.py +++ /dev/null @@ -1,10 +0,0 @@ -class ParserError(Exception): - """ - Raised when a text parser fails to understand a file it been passed - or the resulting parsed text is invalid - """ - pass - - -class ParserUnknownFile(Exception): - pass diff --git a/mayan/apps/redactions/permissions.py b/mayan/apps/redactions/permissions.py index 8b13789179..e3ad39609e 100644 --- a/mayan/apps/redactions/permissions.py +++ b/mayan/apps/redactions/permissions.py @@ -1 +1,20 @@ +from __future__ import absolute_import, unicode_literals +from django.utils.translation import ugettext_lazy as _ + +from mayan.apps.permissions import PermissionNamespace + +namespace = PermissionNamespace(label=_('Redactions'), name='redactions') + +permission_redaction_create = namespace.add_permission( + label=_('Create new redactions'), name='redaction_create' +) +permission_redaction_delete = namespace.add_permission( + label=_('Delete redactions'), name='redaction_delete' +) +permission_redaction_edit = namespace.add_permission( + label=_('Edit redactions'), name='redaction_edit' +) +permission_redaction_view = namespace.add_permission( + label=_('View existing redactions'), name='redaction_view' +) diff --git a/mayan/apps/redactions/templates/redactions/cropper.html b/mayan/apps/redactions/templates/redactions/cropper.html index e82f4edc7e..a042ea840b 100644 --- a/mayan/apps/redactions/templates/redactions/cropper.html +++ b/mayan/apps/redactions/templates/redactions/cropper.html @@ -18,22 +18,10 @@ .cropper-main img { max-width: 100%; } -/* - .cropper-preview { - width: 100%; - overflow: hidden; - } - - .cropper-preview img { - max-width: 100%; - } -*/ {% endblock %} {% block content %} -
-