Add support for showing the current user's events
Add support kwargs to the SourceColumn class. Improve the event widgets, views and tests. Signed-off-by: Roberto Rosario <roberto.rosario.gonzalez@gmail.com>
This commit is contained in:
@@ -104,6 +104,9 @@
|
||||
* Add group created and group edited events.
|
||||
* Add support for SourceColumn widgets.
|
||||
* Improve styling of the template debug view.
|
||||
* Add support for showing the current user's events.
|
||||
* Add support kwargs to the SourceColumn class.
|
||||
* Improve the event widgets, views and tests.
|
||||
|
||||
3.1.11 (2019-04-XX)
|
||||
===================
|
||||
|
||||
@@ -136,6 +136,9 @@ Other changes
|
||||
* Add group created and group edited events.
|
||||
* Add support for SourceColumn widgets.
|
||||
* Improve styling of the template debug view.
|
||||
* Add support for showing the current user's events.
|
||||
* Add support kwargs to the SourceColumn class.
|
||||
* Improve the event widgets, views and tests.
|
||||
|
||||
Removals
|
||||
--------
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.apps import apps
|
||||
from django.contrib.auth import get_user_model
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from mayan.apps.common.apps import MayanAppConfig
|
||||
@@ -11,13 +10,15 @@ from mayan.apps.common.menus import (
|
||||
from mayan.apps.common.widgets import TwoStateWidget
|
||||
from mayan.apps.navigation import SourceColumn
|
||||
|
||||
from .html_widgets import (
|
||||
ObjectLinkWidget, widget_event_actor_link, widget_event_type_link
|
||||
)
|
||||
from .links import (
|
||||
link_events_list, link_event_types_subscriptions_list,
|
||||
link_notification_mark_read, link_notification_mark_read_all,
|
||||
link_user_events, link_user_notifications_list,
|
||||
link_current_user_events, link_event_types_subscriptions_list,
|
||||
link_events_list, link_notification_mark_read,
|
||||
link_notification_mark_read_all, link_user_notifications_list,
|
||||
)
|
||||
from .licenses import * # NOQA
|
||||
from .widgets import event_object_link, event_type_link, event_user_link
|
||||
|
||||
|
||||
class EventsApp(MayanAppConfig):
|
||||
@@ -33,24 +34,23 @@ class EventsApp(MayanAppConfig):
|
||||
Action = apps.get_model(app_label='actstream', model_name='Action')
|
||||
Notification = self.get_model(model_name='Notification')
|
||||
StoredEventType = self.get_model(model_name='StoredEventType')
|
||||
User = get_user_model()
|
||||
|
||||
SourceColumn(
|
||||
source=Action, label=_('Timestamp'), attribute='timestamp'
|
||||
)
|
||||
SourceColumn(
|
||||
source=Action, label=_('Actor'),
|
||||
func=lambda context: event_user_link(context['object'])
|
||||
func=widget_event_actor_link, label=_('Actor'), source=Action
|
||||
)
|
||||
SourceColumn(
|
||||
source=Action, label=_('Event'),
|
||||
func=lambda context: event_type_link(context['object'])
|
||||
func=widget_event_type_link, label=_('Event'), source=Action
|
||||
)
|
||||
SourceColumn(
|
||||
source=Action, label=_('Action object'),
|
||||
func=lambda context: event_object_link(
|
||||
entry=context['object'], attribute='action_object'
|
||||
)
|
||||
attribute='action_object', label=_('Action object'), source=Action,
|
||||
widget=ObjectLinkWidget
|
||||
)
|
||||
SourceColumn(
|
||||
attribute='target', label=_('Target'), source=Action,
|
||||
widget=ObjectLinkWidget
|
||||
)
|
||||
|
||||
SourceColumn(
|
||||
@@ -64,17 +64,20 @@ class EventsApp(MayanAppConfig):
|
||||
source=Notification, label=_('Timestamp'),
|
||||
attribute='action.timestamp'
|
||||
)
|
||||
|
||||
SourceColumn(
|
||||
source=Notification, label=_('Actor'), attribute='action.actor'
|
||||
func=widget_event_actor_link, label=_('Actor'),
|
||||
kwargs={'attribute': 'action'}, source=Notification
|
||||
)
|
||||
SourceColumn(
|
||||
source=Notification, label=_('Event'),
|
||||
func=lambda context: event_type_link(context['object'].action)
|
||||
func=widget_event_type_link, label=_('Event'),
|
||||
kwargs={'attribute': 'action'}, source=Notification
|
||||
)
|
||||
SourceColumn(
|
||||
source=Notification, label=_('Target'),
|
||||
func=lambda context: event_object_link(context['object'].action)
|
||||
attribute='action.target', label=_('Target'), source=Notification,
|
||||
widget=ObjectLinkWidget
|
||||
)
|
||||
|
||||
SourceColumn(
|
||||
source=Notification, label=_('Seen'),
|
||||
func=lambda context: TwoStateWidget(
|
||||
@@ -88,14 +91,13 @@ class EventsApp(MayanAppConfig):
|
||||
menu_object.bind_links(
|
||||
links=(link_notification_mark_read,), sources=(Notification,)
|
||||
)
|
||||
menu_object.bind_links(
|
||||
links=(link_user_events,), sources=(User,)
|
||||
)
|
||||
menu_secondary.bind_links(
|
||||
links=(link_notification_mark_read_all,),
|
||||
sources=('events:user_notifications_list',)
|
||||
)
|
||||
menu_tools.bind_links(links=(link_events_list,))
|
||||
menu_user.bind_links(
|
||||
links=(link_event_types_subscriptions_list,), position=50
|
||||
links=(
|
||||
link_event_types_subscriptions_list, link_current_user_events
|
||||
), position=50
|
||||
)
|
||||
|
||||
82
mayan/apps/events/html_widgets.py
Normal file
82
mayan/apps/events/html_widgets.py
Normal file
@@ -0,0 +1,82 @@
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.apps import apps
|
||||
from django.template import Context, Template
|
||||
from django.urls import reverse
|
||||
from django.utils.encoding import force_text
|
||||
from django.utils.safestring import mark_safe
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from .classes import EventType
|
||||
|
||||
|
||||
class ObjectLinkWidget(object):
|
||||
template_string = '<a href="{{ url }}">{{ object_type }}{{ label }}</a>'
|
||||
|
||||
def __init__(self):
|
||||
self.template = Template(template_string=self.template_string)
|
||||
|
||||
def render(self, name=None, value=None):
|
||||
label = ''
|
||||
object_type = ''
|
||||
url = None
|
||||
|
||||
if value:
|
||||
label = force_text(value)
|
||||
object_type = '{}: '.format(value._meta.verbose_name)
|
||||
try:
|
||||
url = value.get_absolute_url()
|
||||
except AttributeError:
|
||||
url = None
|
||||
|
||||
return self.template.render(
|
||||
context=Context(
|
||||
{'label': label, 'object_type': object_type, 'url': url or '#'}
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def widget_event_actor_link(context, attribute=None):
|
||||
entry = context['object']
|
||||
|
||||
ContentType = apps.get_model(
|
||||
app_label='contenttypes', model_name='ContentType'
|
||||
)
|
||||
|
||||
if attribute:
|
||||
entry = getattr(entry, attribute)
|
||||
|
||||
if entry.actor == entry.target:
|
||||
label = _('System')
|
||||
url = None
|
||||
else:
|
||||
label = entry.actor
|
||||
content_type = ContentType.objects.get_for_model(model=entry.actor)
|
||||
|
||||
url = reverse(
|
||||
viewname='events:events_for_object', kwargs={
|
||||
'app_label': content_type.app_label, 'model': content_type.model,
|
||||
'object_id': entry.actor.pk
|
||||
}
|
||||
)
|
||||
|
||||
if url:
|
||||
return Template(
|
||||
template_string='<a href="{{ url }}">{{ label }}</a>'
|
||||
).render(context=Context({'label': entry.actor, 'url': url}))
|
||||
else:
|
||||
return label
|
||||
|
||||
|
||||
def widget_event_type_link(context, attribute=None):
|
||||
entry = context['object']
|
||||
|
||||
if attribute:
|
||||
entry = getattr(entry, attribute)
|
||||
|
||||
return mark_safe(
|
||||
'<a href="%(url)s">%(label)s</a>' % {
|
||||
'url': reverse(viewname='events:events_by_verb', kwargs={'verb': entry.verb}),
|
||||
'label': EventType.get(name=entry.verb)
|
||||
}
|
||||
)
|
||||
@@ -5,9 +5,8 @@ from mayan.apps.appearance.classes import Icon
|
||||
icon_event_types_subscriptions_list = Icon(
|
||||
driver_name='fontawesome', symbol='list-ol'
|
||||
)
|
||||
icon_events_list = Icon(driver_name='fontawesome', symbol='list-ol')
|
||||
icon_events_for_object = Icon(driver_name='fontawesome', symbol='list-ol')
|
||||
icon_events_user_list = Icon(driver_name='fontawesome', symbol='rss')
|
||||
icon_events_list = Icon(driver_name='fontawesome', symbol='list-ol')
|
||||
icon_object_event_types_user_subcriptions_list = Icon(
|
||||
driver_name='fontawesome', symbol='rss'
|
||||
)
|
||||
|
||||
@@ -41,9 +41,9 @@ def get_unread_notification_count(context):
|
||||
).filter(read=False).count()
|
||||
|
||||
|
||||
link_events_list = Link(
|
||||
icon_class=icon_events_list, permissions=(permission_events_view,),
|
||||
text=_('Events'), view='events:events_list'
|
||||
link_current_user_events = Link(
|
||||
icon_class=icon_events_list, text=_('My events'),
|
||||
view='events:current_user_events'
|
||||
)
|
||||
link_events_details = Link(
|
||||
text=_('Events'), view='events:events_list'
|
||||
@@ -54,6 +54,10 @@ link_events_for_object = Link(
|
||||
permissions=(permission_events_view,), text=_('Events'),
|
||||
view='events:events_for_object',
|
||||
)
|
||||
link_events_list = Link(
|
||||
icon_class=icon_events_list, permissions=(permission_events_view,),
|
||||
text=_('Events'), view='events:events_list'
|
||||
)
|
||||
link_event_types_subscriptions_list = Link(
|
||||
icon_class=icon_event_types_subscriptions_list,
|
||||
text=_('Event subscriptions'),
|
||||
@@ -72,10 +76,6 @@ link_object_event_types_user_subcriptions_list = Link(
|
||||
permissions=(permission_events_view,), text=_('Subscriptions'),
|
||||
view='events:object_event_types_user_subcriptions_list',
|
||||
)
|
||||
link_user_events = Link(
|
||||
args='resolved_object.pk', text=_('User events'),
|
||||
view='events:user_events'
|
||||
)
|
||||
link_user_notifications_list = Link(
|
||||
badge_text=get_unread_notification_count,
|
||||
icon_class=icon_user_notifications_list, text='',
|
||||
|
||||
6
mayan/apps/events/tests/literals.py
Normal file
6
mayan/apps/events/tests/literals.py
Normal file
@@ -0,0 +1,6 @@
|
||||
from __future__ import unicode_literals
|
||||
|
||||
TEST_EVENT_TYPE_NAMESPACE_LABEL = 'test event type namespace label'
|
||||
TEST_EVENT_TYPE_NAMESPACE_NAME = 'test_event_type_namespace_name'
|
||||
TEST_EVENT_TYPE_LABEL = 'test event type label'
|
||||
TEST_EVENT_TYPE_NAME = 'test_event_type_name'
|
||||
20
mayan/apps/events/tests/mixins.py
Normal file
20
mayan/apps/events/tests/mixins.py
Normal file
@@ -0,0 +1,20 @@
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from ..classes import EventTypeNamespace
|
||||
|
||||
from .literals import (
|
||||
TEST_EVENT_TYPE_LABEL, TEST_EVENT_TYPE_NAME,
|
||||
TEST_EVENT_TYPE_NAMESPACE_LABEL, TEST_EVENT_TYPE_NAMESPACE_NAME
|
||||
)
|
||||
|
||||
|
||||
class EventTypeTestMixin(object):
|
||||
def _create_test_event_type(self):
|
||||
self.test_event_type_namespace = EventTypeNamespace(
|
||||
label=TEST_EVENT_TYPE_NAMESPACE_LABEL,
|
||||
name=TEST_EVENT_TYPE_NAMESPACE_NAME
|
||||
)
|
||||
self.test_event_type = self.test_event_type_namespace.add_event_type(
|
||||
label=TEST_EVENT_TYPE_LABEL,
|
||||
name=TEST_EVENT_TYPE_NAME
|
||||
)
|
||||
@@ -1,9 +1,69 @@
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
|
||||
from rest_framework import status
|
||||
|
||||
from mayan.apps.documents.tests import DocumentTestMixin
|
||||
from mayan.apps.rest_api.tests import BaseAPITestCase
|
||||
|
||||
from ..permissions import permission_events_view
|
||||
|
||||
from .mixins import EventTypeTestMixin
|
||||
|
||||
|
||||
class EventTypeNamespaceAPITestCase(EventTypeTestMixin, BaseAPITestCase):
|
||||
def setUp(self):
|
||||
super(EventTypeNamespaceAPITestCase, self).setUp()
|
||||
self._create_test_event_type()
|
||||
|
||||
class EventAPITestCase(BaseAPITestCase):
|
||||
def test_evet_type_list_view(self):
|
||||
response = self.get(viewname='rest_api:event-type-list')
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
|
||||
def test_event_type_namespace_list_view(self):
|
||||
response = self.get(viewname='rest_api:event-type-namespace-list')
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
|
||||
def test_event_type_namespace_event_type_list_view(self):
|
||||
response = self.get(
|
||||
viewname='rest_api:event-type-namespace-event-type-list',
|
||||
kwargs={
|
||||
'name': self.test_event_type_namespace.name
|
||||
}
|
||||
)
|
||||
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
|
||||
|
||||
class ObjectEventAPITestCase(DocumentTestMixin, BaseAPITestCase):
|
||||
auto_upload_document = False
|
||||
|
||||
def setUp(self):
|
||||
super(ObjectEventAPITestCase, self).setUp()
|
||||
self.test_object = self.test_document_type
|
||||
|
||||
content_type = ContentType.objects.get_for_model(model=self.test_object)
|
||||
|
||||
self.view_arguments = {
|
||||
'app_label': content_type.app_label,
|
||||
'model': content_type.model,
|
||||
'object_id': self.test_object.pk
|
||||
}
|
||||
|
||||
def _request_object_event_list_api_view(self):
|
||||
return self.get(
|
||||
viewname='rest_api:object-event-list',
|
||||
kwargs=self.view_arguments
|
||||
)
|
||||
|
||||
def test_object_event_list_view_no_permission(self):
|
||||
response = self._request_object_event_list_api_view()
|
||||
self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
|
||||
|
||||
def test_object_event_list_view_with_access(self):
|
||||
self.grant_access(
|
||||
obj=self.test_object, permission=permission_events_view
|
||||
)
|
||||
response = self._request_object_event_list_api_view()
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
|
||||
@@ -8,15 +8,18 @@ from ..permissions import permission_events_view
|
||||
|
||||
|
||||
class EventsViewTestCase(GenericDocumentViewTestCase):
|
||||
auto_upload_document = False
|
||||
|
||||
def setUp(self):
|
||||
super(EventsViewTestCase, self).setUp()
|
||||
self.test_object = self.test_document_type
|
||||
|
||||
content_type = ContentType.objects.get_for_model(self.test_document)
|
||||
content_type = ContentType.objects.get_for_model(self.test_object)
|
||||
|
||||
self.view_arguments = {
|
||||
'app_label': content_type.app_label,
|
||||
'model': content_type.model,
|
||||
'object_id': self.document.pk
|
||||
'object_id': self.test_object.pk
|
||||
}
|
||||
|
||||
def _request_events_for_object_view(self):
|
||||
@@ -27,19 +30,15 @@ class EventsViewTestCase(GenericDocumentViewTestCase):
|
||||
def test_events_for_object_view_no_permission(self):
|
||||
response = self._request_events_for_object_view()
|
||||
self.assertNotContains(
|
||||
response=response, text=self.test_document.label, status_code=403
|
||||
)
|
||||
self.assertNotContains(
|
||||
response=response, text='otal:', status_code=403
|
||||
response=response, text=self.test_object.label, status_code=404
|
||||
)
|
||||
|
||||
def test_events_for_object_view_with_permission(self):
|
||||
self.grant_permission(permission=permission_events_view)
|
||||
self.grant_access(
|
||||
obj=self.test_object, permission=permission_events_view
|
||||
)
|
||||
|
||||
response = self._request_events_for_object_view()
|
||||
self.assertContains(
|
||||
response=response, text=self.test_document.label, status_code=200
|
||||
)
|
||||
self.assertNotContains(
|
||||
response=response, text='otal: 0', status_code=200
|
||||
response=response, text=self.test_object.label, status_code=200
|
||||
)
|
||||
|
||||
@@ -8,9 +8,10 @@ from .api_views import (
|
||||
APINotificationListView, APIObjectEventListView
|
||||
)
|
||||
from .views import (
|
||||
EventListView, EventTypeSubscriptionListView, NotificationListView,
|
||||
NotificationMarkRead, NotificationMarkReadAll, ObjectEventListView,
|
||||
ObjectEventTypeSubscriptionListView, UserEventListView, VerbEventListView
|
||||
CurrentUserEventListView, EventListView, EventTypeSubscriptionListView,
|
||||
NotificationListView, NotificationMarkRead, NotificationMarkReadAll,
|
||||
ObjectEventListView, ObjectEventTypeSubscriptionListView,
|
||||
VerbEventListView
|
||||
)
|
||||
|
||||
urlpatterns = [
|
||||
@@ -31,15 +32,15 @@ urlpatterns = [
|
||||
regex=r'^notifications/all/mark_read/$',
|
||||
view=NotificationMarkReadAll.as_view(), name='notification_mark_read_all'
|
||||
),
|
||||
url(
|
||||
regex=r'^user/events/$', name='current_user_events',
|
||||
view=CurrentUserEventListView.as_view()
|
||||
),
|
||||
url(
|
||||
regex=r'^user/(?P<app_label>[-\w]+)/(?P<model>[-\w]+)/(?P<object_id>\d+)/subscriptions/$',
|
||||
view=ObjectEventTypeSubscriptionListView.as_view(),
|
||||
name='object_event_types_user_subcriptions_list'
|
||||
),
|
||||
url(
|
||||
regex=r'^user/(?P<pk>\d+)/events/$', view=UserEventListView.as_view(),
|
||||
name='user_events'
|
||||
),
|
||||
url(
|
||||
regex=r'^user/event_types/subscriptions/$',
|
||||
view=EventTypeSubscriptionListView.as_view(),
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
from __future__ import absolute_import, unicode_literals
|
||||
|
||||
from django.contrib import messages
|
||||
from django.contrib.auth import get_user_model
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.http import Http404, HttpResponseRedirect
|
||||
from django.shortcuts import get_object_or_404
|
||||
@@ -13,7 +12,6 @@ from actstream.models import Action, any_stream
|
||||
|
||||
from mayan.apps.acls.models import AccessControlList
|
||||
from mayan.apps.common.generics import FormView, SimpleView
|
||||
from mayan.apps.common.utils import encapsulate
|
||||
from mayan.apps.common.views import SingleObjectListView
|
||||
|
||||
from .classes import EventType, ModelEventType
|
||||
@@ -21,12 +19,11 @@ from .forms import (
|
||||
EventTypeUserRelationshipFormSet, ObjectEventTypeUserRelationshipFormSet
|
||||
)
|
||||
from .icons import (
|
||||
icon_events_list, icon_events_user_list, icon_user_notifications_list
|
||||
icon_events_list, icon_user_notifications_list
|
||||
)
|
||||
from .links import link_event_types_subscriptions_list
|
||||
from .models import StoredEventType
|
||||
from .permissions import permission_events_view
|
||||
from .widgets import event_object_link
|
||||
|
||||
|
||||
class EventListView(SingleObjectListView):
|
||||
@@ -34,14 +31,6 @@ class EventListView(SingleObjectListView):
|
||||
|
||||
def get_extra_context(self):
|
||||
return {
|
||||
'extra_columns': (
|
||||
{
|
||||
'name': _('Target'),
|
||||
'attribute': encapsulate(
|
||||
lambda entry: event_object_link(entry)
|
||||
)
|
||||
},
|
||||
),
|
||||
'hide_object': True,
|
||||
'title': _('Events'),
|
||||
}
|
||||
@@ -154,26 +143,10 @@ class NotificationMarkReadAll(SimpleView):
|
||||
|
||||
|
||||
class ObjectEventListView(EventListView):
|
||||
view_permissions = None
|
||||
view_permission = None
|
||||
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
self.object_content_type = get_object_or_404(
|
||||
klass=ContentType, app_label=self.kwargs['app_label'],
|
||||
model=self.kwargs['model']
|
||||
)
|
||||
|
||||
try:
|
||||
self.content_object = self.object_content_type.get_object_for_this_type(
|
||||
pk=self.kwargs['object_id']
|
||||
)
|
||||
except self.object_content_type.model_class().DoesNotExist:
|
||||
raise Http404
|
||||
|
||||
AccessControlList.objects.check_access(
|
||||
permissions=permission_events_view, user=request.user,
|
||||
obj=self.content_object
|
||||
)
|
||||
|
||||
self.object = self.get_object()
|
||||
return super(
|
||||
ObjectEventListView, self
|
||||
).dispatch(request, *args, **kwargs)
|
||||
@@ -188,13 +161,28 @@ class ObjectEventListView(EventListView):
|
||||
'or using this object.'
|
||||
),
|
||||
'no_results_title': _('There are no events for this object'),
|
||||
'object': self.content_object,
|
||||
'title': _('Events for: %s') % self.content_object,
|
||||
'object': self.object,
|
||||
'title': _('Events for: %s') % self.object,
|
||||
})
|
||||
return context
|
||||
|
||||
def get_object(self):
|
||||
content_type = get_object_or_404(
|
||||
klass=ContentType, app_label=self.kwargs['app_label'],
|
||||
model=self.kwargs['model']
|
||||
)
|
||||
|
||||
queryset = AccessControlList.objects.filter_by_access(
|
||||
permission=permission_events_view,
|
||||
queryset=content_type.model_class().objects.all(),
|
||||
user=self.request.user
|
||||
)
|
||||
return get_object_or_404(
|
||||
klass=queryset, pk=self.kwargs['object_id']
|
||||
)
|
||||
|
||||
def get_object_list(self):
|
||||
return any_stream(self.content_object)
|
||||
return any_stream(self.object)
|
||||
|
||||
|
||||
class ObjectEventTypeSubscriptionListView(FormView):
|
||||
@@ -270,50 +258,14 @@ class ObjectEventTypeSubscriptionListView(FormView):
|
||||
return ModelEventType.get_for_instance(instance=self.get_object())
|
||||
|
||||
|
||||
class UserEventListView(SingleObjectListView):
|
||||
view_permission = permission_events_view
|
||||
|
||||
def get_extra_context(self):
|
||||
return {
|
||||
'extra_columns': (
|
||||
{
|
||||
'name': _('Target'),
|
||||
'attribute': encapsulate(
|
||||
lambda entry: event_object_link(entry)
|
||||
)
|
||||
},
|
||||
),
|
||||
'hide_object': True,
|
||||
'no_results_icon': icon_events_user_list,
|
||||
'no_results_text': _(
|
||||
'Events are actions that have been performed to this '
|
||||
'user account or by this user account.'
|
||||
),
|
||||
'no_results_title': _('There are no events for this user'),
|
||||
'object': self.get_user(),
|
||||
'title': _(
|
||||
'Events for user: %s'
|
||||
) % self.get_user(),
|
||||
}
|
||||
|
||||
def get_object_list(self):
|
||||
return Action.objects.actor(obj=self.get_user())
|
||||
|
||||
def get_user(self):
|
||||
return get_object_or_404(klass=get_user_model(), pk=self.kwargs['pk'])
|
||||
class CurrentUserEventListView(ObjectEventListView):
|
||||
def get_object(self):
|
||||
return self.request.user
|
||||
|
||||
|
||||
class VerbEventListView(SingleObjectListView):
|
||||
def get_extra_context(self):
|
||||
return {
|
||||
'extra_columns': (
|
||||
{
|
||||
'name': _('Target'),
|
||||
'attribute': encapsulate(
|
||||
lambda entry: event_object_link(entry)
|
||||
)
|
||||
},
|
||||
),
|
||||
'hide_object': True,
|
||||
'title': _(
|
||||
'Events of type: %s'
|
||||
|
||||
@@ -1,49 +0,0 @@
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.urls import reverse
|
||||
from django.utils.encoding import force_text
|
||||
from django.utils.safestring import mark_safe
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from .classes import EventType
|
||||
|
||||
|
||||
def event_object_link(entry, attribute='target'):
|
||||
label = ''
|
||||
url = '#'
|
||||
obj_type = ''
|
||||
|
||||
obj = getattr(entry, attribute)
|
||||
|
||||
if obj:
|
||||
obj_type = '{}: '.format(obj._meta.verbose_name)
|
||||
if hasattr(obj, 'get_absolute_url'):
|
||||
url = obj.get_absolute_url()
|
||||
label = force_text(obj)
|
||||
|
||||
return mark_safe(
|
||||
'<a href="%(url)s">%(obj_type)s%(label)s</a>' % {
|
||||
'url': url, 'label': label, 'obj_type': obj_type
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
def event_type_link(entry):
|
||||
return mark_safe(
|
||||
'<a href="%(url)s">%(label)s</a>' % {
|
||||
'url': reverse('events:events_by_verb', kwargs={'verb': entry.verb}),
|
||||
'label': EventType.get(name=entry.verb)
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
def event_user_link(entry):
|
||||
if entry.actor == entry.target:
|
||||
return _('System')
|
||||
else:
|
||||
return mark_safe(
|
||||
'<a href="%(url)s">%(label)s</a>' % {
|
||||
'url': reverse('events:user_events', kwargs={'pk': entry.actor.pk}),
|
||||
'label': entry.actor
|
||||
}
|
||||
)
|
||||
@@ -14,7 +14,7 @@ from django.urls import resolve, reverse
|
||||
from django.utils.encoding import force_str, force_text
|
||||
|
||||
from mayan.apps.common.settings import setting_home_view
|
||||
from mayan.apps.common.utils import return_attrib
|
||||
from mayan.apps.common.utils import resolve_attribute, return_attrib
|
||||
from mayan.apps.permissions import Permission
|
||||
|
||||
from .utils import get_current_view_name
|
||||
@@ -536,11 +536,12 @@ class SourceColumn(object):
|
||||
# unhashable type: list
|
||||
return ()
|
||||
|
||||
def __init__(self, source, label=None, attribute=None, func=None, order=None, widget=None):
|
||||
def __init__(self, source, label=None, attribute=None, func=None, kwargs=None, order=None, widget=None):
|
||||
self.source = source
|
||||
self._label = label
|
||||
self.attribute = attribute
|
||||
self.func = func
|
||||
self.kwargs = kwargs or {}
|
||||
self.order = order or 0
|
||||
self.__class__._registry.setdefault(source, [])
|
||||
self.__class__._registry[source].append(self)
|
||||
@@ -561,9 +562,12 @@ class SourceColumn(object):
|
||||
|
||||
def resolve(self, context):
|
||||
if self.attribute:
|
||||
result = return_attrib(context['object'], self.attribute)
|
||||
result = resolve_attribute(
|
||||
attribute=self.attribute, kwargs=self.kwargs,
|
||||
obj=context['object']
|
||||
)
|
||||
elif self.func:
|
||||
result = self.func(context=context)
|
||||
result = self.func(context=context, **self.kwargs)
|
||||
|
||||
if self.widget:
|
||||
widget_instance = self.widget()
|
||||
|
||||
Reference in New Issue
Block a user