From eb878c165bc587da1a695930c7c705115c74bebe Mon Sep 17 00:00:00 2001 From: Roberto Rosario Date: Wed, 29 Oct 2014 20:17:19 -0400 Subject: [PATCH] Revert "Issue #56, #8, now that metadata types are automatically added to a document upon type change, there is no more need for the document metadata add and remove code, view, API" This reverts commit c390fc21d765f436d32e25e9276b4dd1a60e4279. Re adding this feature, only required metadata should be automatically added, optional metadata would be added by the user --- mayan/apps/metadata/__init__.py | 14 ++- mayan/apps/metadata/api_views.py | 28 +++++- mayan/apps/metadata/links.py | 9 +- mayan/apps/metadata/permissions.py | 2 + mayan/apps/metadata/urls.py | 4 + mayan/apps/metadata/views.py | 152 ++++++++++++++++++++++++++++- 6 files changed, 200 insertions(+), 9 deletions(-) diff --git a/mayan/apps/metadata/__init__.py b/mayan/apps/metadata/__init__.py index 47ee4db85b..e495204f51 100644 --- a/mayan/apps/metadata/__init__.py +++ b/mayan/apps/metadata/__init__.py @@ -15,12 +15,16 @@ from project_setup.api import register_setup from rest_api.classes import APIEndPoint from .api import get_metadata_string -from .links import (metadata_edit, metadata_multiple_edit, metadata_view, +from .links import (metadata_add, metadata_edit, metadata_multiple_add, + metadata_multiple_edit, metadata_multiple_remove, + metadata_remove, metadata_view, setup_document_type_metadata, setup_metadata_type_create, setup_metadata_type_delete, setup_metadata_type_edit, setup_metadata_type_list) from .models import MetadataType -from .permissions import (PERMISSION_METADATA_DOCUMENT_EDIT, +from .permissions import (PERMISSION_METADATA_DOCUMENT_ADD, + PERMISSION_METADATA_DOCUMENT_EDIT, + PERMISSION_METADATA_DOCUMENT_REMOVE, PERMISSION_METADATA_DOCUMENT_VIEW) from .urls import api_urls @@ -50,16 +54,18 @@ def post_post_document_type_change_metadata(sender, instance, **kwargs): DocumentType.add_to_class('metadata', document_type_metadata) -register_links(['metadata:metadata_edit', 'metadata:metadata_view'], [metadata_edit], menu_name='sidebar') +register_links(['metadata:metadata_add', 'metadata:metadata_edit', 'metadata:metadata_remove', 'metadata:metadata_view'], [metadata_add, metadata_edit, metadata_remove], menu_name='sidebar') register_links(Document, [metadata_view], menu_name='form_header') register_links(DocumentType, [setup_document_type_metadata]) register_links(MetadataType, [setup_metadata_type_edit, setup_metadata_type_delete]) register_links([MetadataType, 'metadata:setup_metadata_type_list', 'metadata:setup_metadata_type_create'], [setup_metadata_type_list, setup_metadata_type_create], menu_name='secondary_menu') +register_links([Document], [link_spacer, metadata_multiple_add, metadata_multiple_edit, metadata_multiple_remove], menu_name='multi_item_links') register_setup(setup_metadata_type_list) class_permissions(Document, [ - PERMISSION_METADATA_DOCUMENT_EDIT, PERMISSION_METADATA_DOCUMENT_VIEW, + PERMISSION_METADATA_DOCUMENT_ADD, PERMISSION_METADATA_DOCUMENT_EDIT, + PERMISSION_METADATA_DOCUMENT_REMOVE, PERMISSION_METADATA_DOCUMENT_VIEW, ]) register_model_list_columns(Document, [ diff --git a/mayan/apps/metadata/api_views.py b/mayan/apps/metadata/api_views.py index eb7fd57a02..6e2739790f 100644 --- a/mayan/apps/metadata/api_views.py +++ b/mayan/apps/metadata/api_views.py @@ -16,7 +16,9 @@ from rest_api.filters import MayanObjectPermissionsFilter from rest_api.permissions import MayanPermission from .models import DocumentMetadata, MetadataType -from .permissions import (PERMISSION_METADATA_DOCUMENT_EDIT, +from .permissions import (PERMISSION_METADATA_DOCUMENT_ADD, + PERMISSION_METADATA_DOCUMENT_REMOVE, + PERMISSION_METADATA_DOCUMENT_EDIT, PERMISSION_METADATA_DOCUMENT_VIEW, PERMISSION_METADATA_TYPE_CREATE, PERMISSION_METADATA_TYPE_DELETE, @@ -72,8 +74,15 @@ class APIMetadataTypeView(generics.RetrieveUpdateDestroyAPIView): return super(APIMetadataTypeView, self).put(*args, **kwargs) -class APIDocumentMetadataListView(generics.ListAPIView): +class APIDocumentMetadataListView(generics.ListCreateAPIView): + """ + Returns a list of all the metadata of a document. + """ + serializer_class = DocumentMetadataSerializer + permission_classes = (MayanPermission,) + + mayan_view_permissions = {'POST': [PERMISSION_METADATA_DOCUMENT_ADD]} def get_queryset(self): document = get_object_or_404(Document, pk=self.kwargs['document_pk']) @@ -89,8 +98,16 @@ class APIDocumentMetadataListView(generics.ListAPIView): """Returns a list of selected document's metadata types and values.""" return super(APIDocumentMetadataListView, self).get(*args, **kwargs) + def post(self, *args, **kwargs): + """Add an existing metadata type and value to the selected document.""" + return super(APIDocumentMetadataListView, self).post(*args, **kwargs) + + +class APIDocumentMetadataView(generics.RetrieveUpdateDestroyAPIView): + """ + Returns the selected document metadata details. + """ -class APIDocumentMetadataView(generics.RetrieveUpdateAPIView): serializer_class = DocumentMetadataSerializer queryset = DocumentMetadata.objects.all() @@ -99,8 +116,13 @@ class APIDocumentMetadataView(generics.RetrieveUpdateAPIView): 'GET': [PERMISSION_METADATA_DOCUMENT_VIEW], 'PUT': [PERMISSION_METADATA_DOCUMENT_EDIT], 'PATCH': [PERMISSION_METADATA_DOCUMENT_EDIT], + 'DELETE': [PERMISSION_METADATA_DOCUMENT_REMOVE] } + def delete(self, *args, **kwargs): + """Delete the selected document metadata type and value.""" + return super(APIDocumentMetadataView, self).delete(*args, **kwargs) + def get(self, *args, **kwargs): """Return the details of the selected document metadata type and value.""" return super(APIDocumentMetadataView, self).get(*args, **kwargs) diff --git a/mayan/apps/metadata/links.py b/mayan/apps/metadata/links.py index ccfa3e8cc5..225599d325 100644 --- a/mayan/apps/metadata/links.py +++ b/mayan/apps/metadata/links.py @@ -4,16 +4,23 @@ from django.utils.translation import ugettext_lazy as _ from documents.permissions import PERMISSION_DOCUMENT_TYPE_EDIT -from .permissions import (PERMISSION_METADATA_DOCUMENT_EDIT, +from .permissions import (PERMISSION_METADATA_DOCUMENT_ADD, + PERMISSION_METADATA_DOCUMENT_EDIT, + PERMISSION_METADATA_DOCUMENT_REMOVE, PERMISSION_METADATA_DOCUMENT_VIEW, PERMISSION_METADATA_TYPE_CREATE, PERMISSION_METADATA_TYPE_DELETE, PERMISSION_METADATA_TYPE_EDIT, PERMISSION_METADATA_TYPE_VIEW) + metadata_edit = {'text': _(u'Edit metadata'), 'view': 'metadata:metadata_edit', 'args': 'object.pk', 'famfam': 'xhtml_go', 'permissions': [PERMISSION_METADATA_DOCUMENT_EDIT]} metadata_view = {'text': _(u'Metadata'), 'view': 'metadata:metadata_view', 'args': 'object.pk', 'famfam': 'xhtml_go', 'permissions': [PERMISSION_METADATA_DOCUMENT_VIEW]} metadata_multiple_edit = {'text': _(u'Edit metadata'), 'view': 'metadata:metadata_multiple_edit', 'famfam': 'xhtml_go', 'permissions': [PERMISSION_METADATA_DOCUMENT_EDIT]} +metadata_add = {'text': _(u'Add metadata'), 'view': 'metadata:metadata_add', 'args': 'object.pk', 'famfam': 'xhtml_add', 'permissions': [PERMISSION_METADATA_DOCUMENT_ADD]} +metadata_multiple_add = {'text': _(u'Add metadata'), 'view': 'metadata:metadata_multiple_add', 'famfam': 'xhtml_add', 'permissions': [PERMISSION_METADATA_DOCUMENT_ADD]} +metadata_remove = {'text': _(u'Remove metadata'), 'view': 'metadata:metadata_remove', 'args': 'object.pk', 'famfam': 'xhtml_delete', 'permissions': [PERMISSION_METADATA_DOCUMENT_REMOVE]} +metadata_multiple_remove = {'text': _(u'Remove metadata'), 'view': 'metadata:metadata_multiple_remove', 'famfam': 'xhtml_delete', 'permissions': [PERMISSION_METADATA_DOCUMENT_REMOVE]} setup_document_type_metadata = {'text': _(u'Metadata'), 'view': 'metadata:setup_document_type_metadata', 'args': 'document_type.pk', 'famfam': 'xhtml', 'permissions': [PERMISSION_DOCUMENT_TYPE_EDIT]} diff --git a/mayan/apps/metadata/permissions.py b/mayan/apps/metadata/permissions.py index 4d557e59ba..1ca36fe4e4 100644 --- a/mayan/apps/metadata/permissions.py +++ b/mayan/apps/metadata/permissions.py @@ -6,6 +6,8 @@ from permissions.models import Permission, PermissionNamespace metadata_namespace = PermissionNamespace('metadata', _(u'Metadata')) PERMISSION_METADATA_DOCUMENT_EDIT = Permission.objects.register(metadata_namespace, 'metadata_document_edit', _(u'Edit a document\'s metadata')) +PERMISSION_METADATA_DOCUMENT_ADD = Permission.objects.register(metadata_namespace, 'metadata_document_add', _(u'Add metadata to a document')) +PERMISSION_METADATA_DOCUMENT_REMOVE = Permission.objects.register(metadata_namespace, 'metadata_document_remove', _(u'Remove metadata from a document')) PERMISSION_METADATA_DOCUMENT_VIEW = Permission.objects.register(metadata_namespace, 'metadata_document_view', _(u'View metadata from a document')) metadata_setup_namespace = PermissionNamespace('metadata_setup', _(u'Metadata setup')) diff --git a/mayan/apps/metadata/urls.py b/mayan/apps/metadata/urls.py index 51a4f20fdf..49f8131d74 100644 --- a/mayan/apps/metadata/urls.py +++ b/mayan/apps/metadata/urls.py @@ -9,6 +9,10 @@ urlpatterns = patterns('metadata.views', url(r'^(?P\d+)/edit/$', 'metadata_edit', (), 'metadata_edit'), url(r'^(?P\d+)/view/$', 'metadata_view', (), 'metadata_view'), url(r'^multiple/edit/$', 'metadata_multiple_edit', (), 'metadata_multiple_edit'), + url(r'^(?P\d+)/add/$', 'metadata_add', (), 'metadata_add'), + url(r'^multiple/add/$', 'metadata_multiple_add', (), 'metadata_multiple_add'), + url(r'^(?P\d+)/remove/$', 'metadata_remove', (), 'metadata_remove'), + url(r'^multiple/remove/$', 'metadata_multiple_remove', (), 'metadata_multiple_remove'), url(r'^setup/type/list/$', 'setup_metadata_type_list', (), 'setup_metadata_type_list'), url(r'^setup/type/create/$', 'setup_metadata_type_create', (), 'setup_metadata_type_create'), diff --git a/mayan/apps/metadata/views.py b/mayan/apps/metadata/views.py index 2559b87466..dc23d769d3 100644 --- a/mayan/apps/metadata/views.py +++ b/mayan/apps/metadata/views.py @@ -22,7 +22,9 @@ from .classes import MetadataObjectWrapper from .forms import (AddMetadataForm, MetadataFormSet, MetadataRemoveFormSet, MetadataTypeForm) from .models import DocumentMetadata, DocumentTypeDefaults, MetadataType -from .permissions import (PERMISSION_METADATA_DOCUMENT_EDIT, +from .permissions import (PERMISSION_METADATA_DOCUMENT_ADD, + PERMISSION_METADATA_DOCUMENT_EDIT, + PERMISSION_METADATA_DOCUMENT_REMOVE, PERMISSION_METADATA_DOCUMENT_VIEW, PERMISSION_METADATA_TYPE_CREATE, PERMISSION_METADATA_TYPE_DELETE, @@ -113,6 +115,154 @@ def metadata_multiple_edit(request): return metadata_edit(request, document_id_list=request.GET.get('id_list', '')) +def metadata_add(request, document_id=None, document_id_list=None): + if document_id: + documents = [get_object_or_404(Document, pk=document_id)] + elif document_id_list: + documents = [get_object_or_404(Document, pk=document_id) for document_id in document_id_list.split(',')] + + try: + Permission.objects.check_permissions(request.user, [PERMISSION_METADATA_DOCUMENT_ADD]) + except PermissionDenied: + documents = AccessEntry.objects.filter_objects_by_access(PERMISSION_METADATA_DOCUMENT_ADD, request.user, documents) + + if not documents: + messages.error(request, _(u'Must provide at least one document.')) + return HttpResponseRedirect(request.META.get('HTTP_REFERER', reverse('main:home'))) + + for document in documents: + document.add_as_recent_document_for_user(request.user) + + post_action_redirect = reverse('documents:document_list_recent') + + next = request.POST.get('next', request.GET.get('next', request.META.get('HTTP_REFERER', post_action_redirect))) + + if request.method == 'POST': + form = AddMetadataForm(request.POST) + if form.is_valid(): + metadata_type = form.cleaned_data['metadata_type'] + for document in documents: + document_metadata, created = DocumentMetadata.objects.get_or_create(document=document, metadata_type=metadata_type, defaults={'value': u''}) + if created: + messages.success(request, _(u'Metadata type: %(metadata_type)s successfully added to document %(document)s.') % { + 'metadata_type': metadata_type, 'document': document}) + else: + messages.warning(request, _(u'Metadata type: %(metadata_type)s already present in document %(document)s.') % { + 'metadata_type': metadata_type, 'document': document}) + + if len(documents) == 1: + return HttpResponseRedirect(u'%s?%s' % ( + reverse('metadata:metadata_edit', args=[document.pk]), + urlencode({'next': next})) + ) + elif len(documents) > 1: + return HttpResponseRedirect(u'%s?%s' % ( + reverse('metadata:metadata_multiple_edit'), + urlencode({'id_list': document_id_list, 'next': next})) + ) + + else: + form = AddMetadataForm() + + context = { + 'form': form, + 'next': next, + } + if len(documents) == 1: + context['object'] = documents[0] + context['title'] = _(u'Add metadata type to document: %s') % ', '.join([unicode(d) for d in documents]) + elif len(documents) > 1: + context['title'] = _(u'Add metadata type to documents: %s') % ', '.join([unicode(d) for d in documents]) + + return render_to_response('main/generic_form.html', context, + context_instance=RequestContext(request)) + + +def metadata_multiple_add(request): + return metadata_add(request, document_id_list=request.GET.get('id_list', [])) + + +def metadata_remove(request, document_id=None, document_id_list=None): + if document_id: + documents = [get_object_or_404(Document, pk=document_id)] + if documents[0].metadata.count() == 0: + messages.warning(request, _(u'The selected document doesn\'t have any metadata.')) + return HttpResponseRedirect(request.META.get('HTTP_REFERER', reverse('main:home'))) + + elif document_id_list: + documents = [get_object_or_404(Document, pk=document_id) for document_id in document_id_list.split(',')] + + try: + Permission.objects.check_permissions(request.user, [PERMISSION_METADATA_DOCUMENT_REMOVE]) + except PermissionDenied: + documents = AccessEntry.objects.filter_objects_by_access(PERMISSION_METADATA_DOCUMENT_REMOVE, request.user, documents) + + if not documents: + messages.error(request, _(u'Must provide at least one document.')) + return HttpResponseRedirect(request.META.get('HTTP_REFERER', reverse('main:home'))) + + post_action_redirect = reverse('documents:document_list_recent') + + next = request.POST.get('next', request.GET.get('next', request.META.get('HTTP_REFERER', post_action_redirect))) + + metadata = {} + for document in documents: + document.add_as_recent_document_for_user(request.user) + + for item in document.metadata.all(): + value = item.value + if item.metadata_type in metadata: + if value not in metadata[item.metadata_type]: + metadata[item.metadata_type].append(value) + else: + metadata[item.metadata_type] = [value] if value else u'' + + initial = [] + for key, value in metadata.items(): + initial.append({ + 'metadata_type': key, + 'value': u', '.join(value) + }) + + formset = MetadataRemoveFormSet(initial=initial) + if request.method == 'POST': + formset = MetadataRemoveFormSet(request.POST) + if formset.is_valid(): + for document in documents: + + for form in formset.forms: + if form.cleaned_data['update']: + metadata_type = get_object_or_404(MetadataType, pk=form.cleaned_data['id']) + try: + document_metadata = DocumentMetadata.objects.get(document=document, metadata_type=metadata_type) + document_metadata.delete() + messages.success(request, _(u'Successfully remove metadata type: %(metadata_type)s from document: %(document)s.') % { + 'metadata_type': metadata_type, 'document': document}) + except: + messages.error(request, _(u'Error removing metadata type: %(metadata_type)s from document: %(document)s.') % { + 'metadata_type': metadata_type, 'document': document}) + + return HttpResponseRedirect(next) + + context = { + 'form_display_mode_table': True, + 'form': formset, + 'next': next, + } + if len(documents) == 1: + context['object'] = documents[0] + context['title'] = _(u'Remove metadata types from document: %s') % ', '.join([unicode(d) for d in documents]) + elif len(documents) > 1: + context['title'] = _(u'Remove metadata types from documents: %s') % ', '.join([unicode(d) for d in documents]) + + return render_to_response('main/generic_form.html', context, + context_instance=RequestContext(request)) + + +def metadata_multiple_remove(request): + return metadata_remove(request, document_id_list=request.GET.get('id_list', [])) + + def metadata_view(request, document_id): document = get_object_or_404(Document, pk=document_id)