Refactor the workflow for removing tags from single or multiple documents.

This commit is contained in:
Roberto Rosario
2016-12-21 04:37:26 -04:00
parent 272c8a2628
commit 61c5f6eaa0
6 changed files with 106 additions and 169 deletions

View File

@@ -25,6 +25,7 @@ the user links
- Tags are alphabetically ordered by label
- Stop loading theme fonts from the web
- Add support for attaching multiple tags to single or multiple documents.
- Refactor the workflow for removing tags from single and multiple documents.
Removals
--------

View File

@@ -91,7 +91,10 @@ class DocumentCreateWizard(ViewPermissionCheckMixin, SessionWizardView):
return {'user': self.request.user}
if step == STEP_TAGS:
return {'user': self.request.user}
return {
'help_text': _('Tags to be attached.'),
'user': self.request.user
}
return {}

View File

@@ -127,10 +127,6 @@ class TagsApp(MayanAppConfig):
menu_multi_item.bind_links(
links=(link_tag_multiple_delete,), sources=(Tag,)
)
menu_multi_item.bind_links(
links=(link_single_document_multiple_tag_remove,),
sources=(DocumentTag,)
)
menu_object.bind_links(
links=(
link_tag_tagged_item_list, link_tag_edit, link_acl_list,
@@ -139,7 +135,7 @@ class TagsApp(MayanAppConfig):
sources=(Tag,)
)
menu_sidebar.bind_links(
links=(link_tag_attach,),
links=(link_tag_attach, link_single_document_multiple_tag_remove),
sources=(
'tags:document_tags', 'tags:tag_remove',
'tags:tag_multiple_remove', 'tags:tag_attach'

View File

@@ -14,33 +14,21 @@ from .widgets import TagFormWidget
logger = logging.getLogger(__name__)
class TagListForm(forms.Form):
def __init__(self, *args, **kwargs):
user = kwargs.pop('user', None)
logger.debug('user: %s', user)
super(TagListForm, self).__init__(*args, **kwargs)
queryset = AccessControlList.objects.filter_by_access(
permission_tag_view, user, queryset=Tag.objects.all()
)
self.fields['tag'] = forms.ModelChoiceField(
queryset=queryset, label=_('Tags')
)
class TagMultipleSelectionForm(forms.Form):
def __init__(self, *args, **kwargs):
help_text = kwargs.pop('help_text', None)
queryset = kwargs.pop('queryset', Tag.objects.all())
user = kwargs.pop('user', None)
logger.debug('user: %s', user)
super(TagMultipleSelectionForm, self).__init__(*args, **kwargs)
queryset = AccessControlList.objects.filter_by_access(
permission_tag_view, user, queryset=Tag.objects.all()
permission_tag_view, user, queryset=queryset
)
self.fields['tags'] = forms.ModelMultipleChoiceField(
label=_('Tags'), help_text=_('Tags to attach to the document.'),
label=_('Tags'), help_text=help_text,
queryset=queryset, required=False,
widget=TagFormWidget(attrs={'class': 'select2'}, queryset=queryset)
)

View File

@@ -8,9 +8,8 @@ from .api_views import (
)
from .views import (
DocumentTagListView, TagAttachActionView, TagCreateView,
TagDeleteActionView, TagEditView, TagListView, TagTaggedItemListView,
multiple_documents_selection_tag_remove,
single_document_multiple_tag_remove
TagDeleteActionView, TagEditView, TagListView, TagRemoveActionView,
TagTaggedItemListView
)
urlpatterns = [
@@ -31,13 +30,13 @@ urlpatterns = [
),
url(
r'^multiple/remove/document/(?P<document_id>\d+)/$',
single_document_multiple_tag_remove,
r'^multiple/remove/document/(?P<pk>\d+)/$',
TagRemoveActionView.as_view(),
name='single_document_multiple_tag_remove'
),
url(
r'^multiple/remove/document/multiple/$',
multiple_documents_selection_tag_remove,
TagRemoveActionView.as_view(),
name='multiple_documents_selection_tag_remove'
),

View File

@@ -3,11 +3,8 @@ from __future__ import absolute_import, unicode_literals
import logging
from django.contrib import messages
from django.core.urlresolvers import reverse, reverse_lazy
from django.conf import settings
from django.http import HttpResponseRedirect
from django.shortcuts import get_object_or_404, render_to_response
from django.template import RequestContext
from django.core.urlresolvers import reverse_lazy
from django.shortcuts import get_object_or_404
from django.utils.translation import ugettext_lazy as _, ungettext
from acls.models import AccessControlList
@@ -19,7 +16,7 @@ from documents.models import Document
from documents.views import DocumentListView
from documents.permissions import permission_document_view
from .forms import TagMultipleSelectionForm, TagListForm
from .forms import TagMultipleSelectionForm
from .models import Tag
from .permissions import (
permission_tag_attach, permission_tag_create, permission_tag_delete,
@@ -44,8 +41,8 @@ class TagAttachActionView(MultipleObjectFormActionView):
result = {
'submit_label': _('Attach'),
'title': ungettext(
'Attach tag to document',
'Attach tag to documents',
'Attach tags to document',
'Attach tags to documents',
queryset.count()
)
}
@@ -54,14 +51,27 @@ class TagAttachActionView(MultipleObjectFormActionView):
result.update(
{
'object': queryset.first(),
'title': _('Attach tag to document: %s') % queryset.first()
'title': _('Attach tags to document: %s') % queryset.first()
}
)
return result
def get_form_extra_kwargs(self):
return {'user': self.request.user}
queryset = self.get_queryset()
result = {
'help_text': _('Tags to be attached.'),
'user': self.request.user
}
if queryset.count() == 1:
result.update(
{
'queryset': Tag.objects.exclude(pk__in=queryset.first().tags.all())
}
)
return result
def object_action(self, form, instance):
attached_tags = instance.attached_tags()
@@ -218,138 +228,78 @@ class DocumentTagListView(TagListView):
return self.document.attached_tags().all()
def tag_remove(request, document_id=None, document_id_list=None, tag_id=None, tag_id_list=None):
if document_id:
documents = Document.objects.filter(pk=document_id)
elif document_id_list:
documents = Document.objects.filter(pk__in=document_id_list)
class TagRemoveActionView(MultipleObjectFormActionView):
form_class = TagMultipleSelectionForm
model = Document
object_permission = permission_tag_remove
success_message = _('Tag remove request performed on %(count)d document')
success_message_plural = _(
'Tag remove request performed on %(count)d documents'
)
if not documents:
messages.error(
request, _('Must provide at least one tagged document.')
)
return HttpResponseRedirect(
request.META.get(
'HTTP_REFERER', reverse(settings.LOGIN_REDIRECT_URL)
def get_extra_context(self):
queryset = self.get_queryset()
result = {
'submit_label': _('Remove'),
'title': ungettext(
'Remove tags from document',
'Remove tags from documents',
queryset.count()
)
)
}
documents = AccessControlList.objects.filter_by_access(
permission_tag_remove, request.user, documents
)
post_action_redirect = None
previous = request.POST.get('previous', request.GET.get('previous', request.META.get('HTTP_REFERER', reverse(settings.LOGIN_REDIRECT_URL))))
next = request.POST.get('next', request.GET.get('next', post_action_redirect if post_action_redirect else request.META.get('HTTP_REFERER', reverse(settings.LOGIN_REDIRECT_URL))))
context = {
'previous': previous,
'next': next,
}
template = 'appearance/generic_confirm.html'
if tag_id:
tags = Tag.objects.filter(pk=tag_id)
elif tag_id_list:
tags = Tag.objects.filter(pk__in=tag_id_list)
else:
template = 'appearance/generic_form.html'
if request.method == 'POST':
form = TagListForm(request.POST, user=request.user)
if form.is_valid():
tags = Tag.objects.filter(pk=form.cleaned_data['tag'].pk)
else:
if not tag_id and not tag_id_list:
form = TagListForm(user=request.user)
tags = Tag.objects.none()
context['form'] = form
if len(documents) == 1:
context['object'] = documents.first()
context['title'] = _(
'Remove tag from document: %s.'
) % ', '.join([unicode(d) for d in documents])
elif len(documents) > 1:
context['title'] = _(
'Remove tag from documents: %s.'
) % ', '.join([unicode(d) for d in documents])
if tags:
if tags.count() == 1:
if documents.count() == 1:
context['object'] = documents.first()
context['title'] = _(
'Remove the tag "%(tag)s" from the document: %(document)s?'
) % {
'tag': ', '.join([unicode(d) for d in tags]),
'document': ', '.join([unicode(d) for d in documents])
if queryset.count() == 1:
result.update(
{
'object': queryset.first(),
'title': _('Remove tags from document: %s') % queryset.first()
}
)
return result
def get_form_extra_kwargs(self):
queryset = self.get_queryset()
result = {
'help_text': _('Tags to be removed.'),
'user': self.request.user
}
if queryset.count() == 1:
result.update(
{
'queryset': queryset.first().tags.all()
}
)
return result
def object_action(self, form, instance):
attached_tags = instance.attached_tags()
for tag in form.cleaned_data['tags']:
AccessControlList.objects.check_access(
obj=tag, permissions=permission_tag_view,
user=self.request.user
)
if tag not in attached_tags:
messages.warning(
self.request, _(
'Document "%(document)s" wasn\'t tagged as "%(tag)s'
) % {
'document': instance, 'tag': tag
}
)
else:
context['title'] = _(
'Remove the tag "%(tag)s" from the documents: %(documents)s?'
) % {
'tag': ', '.join([unicode(d) for d in tags]),
'documents': ', '.join([unicode(d) for d in documents])
}
elif tags.count() > 1:
if documents.count() == 1:
context['object'] = documents.first()
context['title'] = _(
'Remove the tags: %(tags)s from the document: %(document)s?'
) % {
'tags': ', '.join([unicode(d) for d in tags]),
'document': ', '.join([unicode(d) for d in documents])
}
else:
context['title'] = _(
'Remove the tags %(tags)s from the documents: %(documents)s?'
) % {
'tags': ', '.join([unicode(d) for d in tags]),
'documents': ', '.join([unicode(d) for d in documents])
}
if request.method == 'POST':
for document in documents:
for tag in tags:
if tag not in document.attached_tags().all():
messages.warning(
request, _(
'Document "%(document)s" wasn\'t tagged as "%(tag)s"'
) % {
'document': document, 'tag': tag
}
)
else:
tag.documents.remove(document)
messages.success(
request, _(
'Tag "%(tag)s" removed successfully from document "%(document)s".'
) % {
'document': document, 'tag': tag
}
)
return HttpResponseRedirect(next)
else:
return render_to_response(
template, context, context_instance=RequestContext(request)
)
def single_document_multiple_tag_remove(request, document_id):
return tag_remove(
request, document_id=document_id,
tag_id_list=request.GET.get(
'id_list', request.POST.get('id_list', '')
).split(',')
)
def multiple_documents_selection_tag_remove(request):
return tag_remove(
request, document_id_list=request.GET.get(
'id_list', request.POST.get('id_list', '')
).split(',')
)
tag.documents.remove(instance)
messages.success(
self.request,
_(
'Tag "%(tag)s" removed successfully from document '
'"%(document)s".'
) % {
'document': instance, 'tag': tag
}
)