From 596b5ccf677fdeaa6f3a62d334dc2b19665f3d49 Mon Sep 17 00:00:00 2001 From: Roberto Rosario Date: Mon, 1 Jul 2019 15:43:15 -0400 Subject: [PATCH] MVP of the weblinks app Signed-off-by: Roberto Rosario --- mayan/apps/linking/apps.py | 2 +- mayan/apps/weblinks/__init__.py | 3 + mayan/apps/weblinks/admin.py | 15 ++ mayan/apps/weblinks/apps.py | 123 +++++++++ mayan/apps/weblinks/events.py | 16 ++ mayan/apps/weblinks/forms.py | 11 + mayan/apps/weblinks/icons.py | 22 ++ mayan/apps/weblinks/links.py | 63 +++++ mayan/apps/weblinks/managers.py | 16 ++ .../apps/weblinks/migrations/0001_initial.py | 42 ++++ mayan/apps/weblinks/migrations/__init__.py | 0 mayan/apps/weblinks/models.py | 90 +++++++ mayan/apps/weblinks/permissions.py | 23 ++ mayan/apps/weblinks/urls.py | 47 ++++ mayan/apps/weblinks/views.py | 233 ++++++++++++++++++ mayan/settings/base.py | 1 + 16 files changed, 706 insertions(+), 1 deletion(-) create mode 100644 mayan/apps/weblinks/__init__.py create mode 100644 mayan/apps/weblinks/admin.py create mode 100644 mayan/apps/weblinks/apps.py create mode 100644 mayan/apps/weblinks/events.py create mode 100644 mayan/apps/weblinks/forms.py create mode 100644 mayan/apps/weblinks/icons.py create mode 100644 mayan/apps/weblinks/links.py create mode 100644 mayan/apps/weblinks/managers.py create mode 100644 mayan/apps/weblinks/migrations/0001_initial.py create mode 100644 mayan/apps/weblinks/migrations/__init__.py create mode 100644 mayan/apps/weblinks/models.py create mode 100644 mayan/apps/weblinks/permissions.py create mode 100644 mayan/apps/weblinks/urls.py create mode 100644 mayan/apps/weblinks/views.py diff --git a/mayan/apps/linking/apps.py b/mayan/apps/linking/apps.py index 57d4ea76ad..aca8761959 100644 --- a/mayan/apps/linking/apps.py +++ b/mayan/apps/linking/apps.py @@ -58,7 +58,7 @@ class LinkingApp(MayanAppConfig): ModelEventType.register( event_types=( - event_smart_link_created, event_smart_link_edited + event_smart_link_edited, ), model=SmartLink ) diff --git a/mayan/apps/weblinks/__init__.py b/mayan/apps/weblinks/__init__.py new file mode 100644 index 0000000000..f7b9803f43 --- /dev/null +++ b/mayan/apps/weblinks/__init__.py @@ -0,0 +1,3 @@ +from __future__ import unicode_literals + +default_app_config = 'mayan.apps.weblinks.apps.WebLinksApp' diff --git a/mayan/apps/weblinks/admin.py b/mayan/apps/weblinks/admin.py new file mode 100644 index 0000000000..c29ac45e52 --- /dev/null +++ b/mayan/apps/weblinks/admin.py @@ -0,0 +1,15 @@ +from __future__ import unicode_literals + +from django.contrib import admin +from .models import WebLink + + +@admin.register(WebLink) +class WebLinkAdmin(admin.ModelAdmin): + def document_type_list(self, instance): + return ','.join( + instance.document_types.values_list('label', flat=True) + ) + + filter_horizontal = ('document_types',) + list_display = ('label', 'template', 'enabled', 'document_type_list') diff --git a/mayan/apps/weblinks/apps.py b/mayan/apps/weblinks/apps.py new file mode 100644 index 0000000000..0321170269 --- /dev/null +++ b/mayan/apps/weblinks/apps.py @@ -0,0 +1,123 @@ +from __future__ import unicode_literals + +from django.apps import apps +from django.utils.translation import ugettext_lazy as _ + +from mayan.apps.acls.classes import ModelPermission +from mayan.apps.acls.links import link_acl_list +from mayan.apps.acls.permissions import permission_acl_edit, permission_acl_view +from mayan.apps.common.apps import MayanAppConfig +from mayan.apps.common.html_widgets import TwoStateWidget +from mayan.apps.common.menus import ( + menu_facet, menu_list_facet, menu_object, menu_secondary, menu_setup +) +from mayan.apps.events.classes import ModelEventType +from mayan.apps.events.links import ( + link_events_for_object, link_object_event_types_user_subcriptions_list +) +from mayan.apps.navigation.classes import SourceColumn +from .events import event_web_link_edited +from .links import ( + link_document_type_web_links, link_document_web_link_list, + link_web_link_create, link_web_link_delete, link_web_link_document_types, + link_web_link_edit, link_web_link_instance_view, + link_web_link_list, link_web_link_setup +) +from .permissions import ( + permission_web_link_delete, permission_web_link_edit, + permission_web_link_instance_view, permission_web_link_view +) + + +class WebLinksApp(MayanAppConfig): + app_namespace = 'weblinks' + app_url = 'weblinks' + has_rest_api = False + has_tests = False + name = 'mayan.apps.weblinks' + verbose_name = _('Links') + + def ready(self): + super(WebLinksApp, self).ready() + from actstream import registry + + Document = apps.get_model( + app_label='documents', model_name='Document' + ) + DocumentType = apps.get_model( + app_label='documents', model_name='DocumentType' + ) + + ResolvedWebLink = self.get_model(model_name='ResolvedWebLink') + WebLink = self.get_model(model_name='WebLink') + + ModelEventType.register( + event_types=( + event_web_link_edited, + ), model=WebLink + ) + + ModelPermission.register( + model=Document, permissions=( + permission_web_link_instance_view, + ) + ) + ModelPermission.register( + model=DocumentType, permissions=( + permission_web_link_instance_view, + ) + ) + ModelPermission.register( + model=WebLink, permissions=( + permission_acl_edit, permission_acl_view, + permission_web_link_delete, permission_web_link_edit, + permission_web_link_view + ) + ) + + SourceColumn( + attribute='label', is_identifier=True, is_sortable=True, + source=ResolvedWebLink + ) + SourceColumn( + attribute='label', is_identifier=True, is_sortable=True, + source=WebLink + ) + SourceColumn( + attribute='enabled', is_sortable=True, source=WebLink, + widget=TwoStateWidget + ) + + menu_facet.bind_links( + links=(link_document_web_link_list,), + sources=(Document,) + ) + menu_list_facet.bind_links( + links=( + link_acl_list, link_events_for_object, + link_web_link_document_types, + link_object_event_types_user_subcriptions_list, + ), sources=(WebLink,) + ) + menu_list_facet.bind_links( + links=(link_document_type_web_links,), sources=(DocumentType,) + ) + menu_object.bind_links( + links=( + link_web_link_delete, link_web_link_edit + ), sources=(WebLink,) + ) + menu_object.bind_links( + links=(link_web_link_instance_view,), + sources=(ResolvedWebLink,) + ) + menu_secondary.bind_links( + links=(link_web_link_list, link_web_link_create), + sources=( + WebLink, 'linking:web_link_list', + 'linking:web_link_create' + ) + ) + menu_setup.bind_links(links=(link_web_link_setup,)) + + registry.register(WebLink) diff --git a/mayan/apps/weblinks/events.py b/mayan/apps/weblinks/events.py new file mode 100644 index 0000000000..42ebf0c0fa --- /dev/null +++ b/mayan/apps/weblinks/events.py @@ -0,0 +1,16 @@ +from __future__ import absolute_import, unicode_literals + +from django.utils.translation import ugettext_lazy as _ + +from mayan.apps.events.classes import EventTypeNamespace + +namespace = EventTypeNamespace( + label=_('Web links'), name='linking' +) + +event_web_link_created = namespace.add_event_type( + label=_('Web link created'), name='web_link_created' +) +event_web_link_edited = namespace.add_event_type( + label=_('Web link edited'), name='web_link_edited' +) diff --git a/mayan/apps/weblinks/forms.py b/mayan/apps/weblinks/forms.py new file mode 100644 index 0000000000..e5e6beae69 --- /dev/null +++ b/mayan/apps/weblinks/forms.py @@ -0,0 +1,11 @@ +from __future__ import unicode_literals + +from django import forms + +from .models import WebLink + + +class WebLinkForm(forms.ModelForm): + class Meta: + fields = ('label', 'template', 'enabled') + model = WebLink diff --git a/mayan/apps/weblinks/icons.py b/mayan/apps/weblinks/icons.py new file mode 100644 index 0000000000..9de99ddc33 --- /dev/null +++ b/mayan/apps/weblinks/icons.py @@ -0,0 +1,22 @@ +from __future__ import absolute_import, unicode_literals + +from mayan.apps.appearance.classes import Icon +from mayan.apps.documents.icons import icon_document_type + +icon_web_link = Icon(driver_name='fontawesome', symbol='external-link-alt') +icon_document_type_web_links = icon_web_link +icon_document_web_link_list = Icon( + driver_name='fontawesome', symbol='external-link-alt' +) +icon_web_link_create = Icon( + driver_name='fontawesome-dual', primary_symbol='external-link-alt', + secondary_symbol='plus' +) +icon_web_link_delete = Icon(driver_name='fontawesome', symbol='times') +icon_web_link_document_types = icon_document_type +icon_web_link_edit = Icon(driver_name='fontawesome', symbol='pencil-alt') +icon_web_link_instance_view = Icon( + driver_name='fontawesome', symbol='external-link-alt' +) +icon_web_link_setup = icon_web_link +icon_web_link_list = icon_web_link diff --git a/mayan/apps/weblinks/links.py b/mayan/apps/weblinks/links.py new file mode 100644 index 0000000000..e787c910f3 --- /dev/null +++ b/mayan/apps/weblinks/links.py @@ -0,0 +1,63 @@ +from __future__ import unicode_literals + +from django.utils.translation import ugettext_lazy as _ + +from mayan.apps.documents.permissions import permission_document_type_edit +from mayan.apps.navigation.classes import Link + +from .permissions import ( + permission_web_link_create, permission_web_link_delete, + permission_web_link_edit, permission_web_link_instance_view, + permission_web_link_view +) + +link_document_type_web_links = Link( + args='resolved_object.pk', + icon_class_path='mayan.apps.weblinks.icons.icon_document_type_web_links', + permissions=(permission_document_type_edit,), text=_('Web links'), + view='weblinks:document_type_web_links', +) +link_web_link_create = Link( + icon_class_path='mayan.apps.weblinks.icons.icon_web_link_create', + permissions=(permission_web_link_create,), + text=_('Create new web link'), view='weblinks:web_link_create' +) +link_web_link_delete = Link( + args='object.pk', + icon_class_path='mayan.apps.weblinks.icons.icon_web_link_delete', + permissions=(permission_web_link_delete,), + tags='dangerous', text=_('Delete'), view='weblinks:web_link_delete', +) +link_web_link_document_types = Link( + args='object.pk', + icon_class_path='mayan.apps.weblinks.icons.icon_web_link_document_types', + permissions=(permission_web_link_edit,), + text=_('Document types'), view='weblinks:web_link_document_types', +) +link_web_link_edit = Link( + args='object.pk', + icon_class_path='mayan.apps.weblinks.icons.icon_web_link_edit', + permissions=(permission_web_link_edit,), + text=_('Edit'), view='weblinks:web_link_edit', +) +link_web_link_instance_view = Link( + icon_class_path='mayan.apps.weblinks.icons.icon_web_link_instance_view', + args=('document.pk', 'object.pk',), + permissions=(permission_web_link_instance_view,), tags='new_window', + text=_('Navigate'), view='weblinks:web_link_instance_view', +) +link_document_web_link_list = Link( + args='resolved_object.pk', + icon_class_path='mayan.apps.weblinks.icons.icon_document_web_link_list', + permissions=(permission_web_link_instance_view,), text=_('Web links'), + view='weblinks:document_web_link_list', +) +link_web_link_list = Link( + icon_class_path='mayan.apps.weblinks.icons.icon_web_link_list', + text=_('Web links'), view='weblinks:web_link_list' +) +link_web_link_setup = Link( + icon_class_path='mayan.apps.weblinks.icons.icon_web_link_setup', + permissions=(permission_web_link_create,), text=_('Web links'), + view='weblinks:web_link_list' +) diff --git a/mayan/apps/weblinks/managers.py b/mayan/apps/weblinks/managers.py new file mode 100644 index 0000000000..4e56f22a43 --- /dev/null +++ b/mayan/apps/weblinks/managers.py @@ -0,0 +1,16 @@ +from django.db import models + +from mayan.apps.acls.models import AccessControlList + +from .permissions import permission_web_link_instance_view + + +class WebLinkManager(models.Manager): + def get_for(self, document, user): + queryset = self.filter( + document_types=document.document_type, enabled=True + ) + return AccessControlList.objects.restrict_queryset( + permission=permission_web_link_instance_view, + queryset=queryset, user=user + ) diff --git a/mayan/apps/weblinks/migrations/0001_initial.py b/mayan/apps/weblinks/migrations/0001_initial.py new file mode 100644 index 0000000000..6887235122 --- /dev/null +++ b/mayan/apps/weblinks/migrations/0001_initial.py @@ -0,0 +1,42 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.20 on 2019-07-01 19:42 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ('documents', '0047_auto_20180917_0737'), + ] + + operations = [ + migrations.CreateModel( + name='WebLink', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('label', models.CharField(db_index=True, max_length=96, verbose_name='Label')), + ('template', models.TextField(verbose_name='Template')), + ('enabled', models.BooleanField(default=True, verbose_name='Enabled')), + ('document_types', models.ManyToManyField(related_name='web_links', to='documents.DocumentType', verbose_name='Document types')), + ], + options={ + 'ordering': ('label',), + 'verbose_name': 'Web link', + 'verbose_name_plural': 'Web links', + }, + ), + migrations.CreateModel( + name='ResolvedWebLink', + fields=[ + ], + options={ + 'proxy': True, + 'indexes': [], + }, + bases=('weblinks.weblink',), + ), + ] diff --git a/mayan/apps/weblinks/migrations/__init__.py b/mayan/apps/weblinks/migrations/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/mayan/apps/weblinks/models.py b/mayan/apps/weblinks/models.py new file mode 100644 index 0000000000..da0a6d1d6a --- /dev/null +++ b/mayan/apps/weblinks/models.py @@ -0,0 +1,90 @@ +from __future__ import unicode_literals + +from django.db import models, transaction +from django.template import Context, Template +from django.utils.encoding import python_2_unicode_compatible +from django.utils.translation import ugettext_lazy as _ + +from mayan.apps.documents.events import event_document_type_edited +from mayan.apps.documents.models import DocumentType + +from .events import event_web_link_created, event_web_link_edited +from .managers import WebLinkManager + + +@python_2_unicode_compatible +class WebLink(models.Model): + """ + This model stores the basic fields for a web link. Web links allow + generating links from documents to external resources. + """ + label = models.CharField( + db_index=True, max_length=96, verbose_name=_('Label') + ) + template = models.TextField(verbose_name=_('Template')) + enabled = models.BooleanField(default=True, verbose_name=_('Enabled')) + document_types = models.ManyToManyField( + related_name='web_links', to=DocumentType, + verbose_name=_('Document types') + ) + + objects = WebLinkManager() + + class Meta: + ordering = ('label',) + verbose_name = _('Web link') + verbose_name_plural = _('Web links') + + def __str__(self): + return self.label + + def document_types_add(self, queryset, _user=None): + with transaction.atomic(): + event_web_link_edited.commit( + actor=_user, target=self + ) + for obj in queryset: + self.document_types.add(obj) + event_document_type_edited.commit( + actor=_user, action_object=self, target=obj + ) + + def document_types_remove(self, queryset, _user=None): + with transaction.atomic(): + event_web_link_edited.commit( + actor=_user, target=self + ) + for obj in queryset: + self.document_types.remove(obj) + event_document_type_edited.commit( + actor=_user, action_object=self, target=obj + ) + + def save(self, *args, **kwargs): + _user = kwargs.pop('_user', None) + + with transaction.atomic(): + is_new = not self.pk + super(WebLink, self).save(*args, **kwargs) + if is_new: + event_web_link_created.commit( + actor=_user, target=self + ) + else: + event_web_link_edited.commit( + actor=_user, target=self + ) + + +class ResolvedWebLink(WebLink): + """ + Proxy model to represent an already resolved web link. Used for easier + colums registration. + """ + class Meta: + proxy = True + + def get_url_for(self, document): + context = Context({'document': document}) + + return Template(self.template).render(context=context) diff --git a/mayan/apps/weblinks/permissions.py b/mayan/apps/weblinks/permissions.py new file mode 100644 index 0000000000..2c377d960e --- /dev/null +++ b/mayan/apps/weblinks/permissions.py @@ -0,0 +1,23 @@ +from __future__ import absolute_import, unicode_literals + +from django.utils.translation import ugettext_lazy as _ + +from mayan.apps.permissions import PermissionNamespace + +namespace = PermissionNamespace(label=_('Web links'), name='web_links') + +permission_web_link_create = namespace.add_permission( + label=_('Create new web links'), name='web_link_create' +) +permission_web_link_delete = namespace.add_permission( + label=_('Delete web links'), name='web_link_delete' +) +permission_web_link_edit = namespace.add_permission( + label=_('Edit web links'), name='web_link_edit' +) +permission_web_link_view = namespace.add_permission( + label=_('View existing web links'), name='web_link_view' +) +permission_web_link_instance_view = namespace.add_permission( + label=_('View web link instances'), name='web_link_instance_view' +) diff --git a/mayan/apps/weblinks/urls.py b/mayan/apps/weblinks/urls.py new file mode 100644 index 0000000000..01445bbc38 --- /dev/null +++ b/mayan/apps/weblinks/urls.py @@ -0,0 +1,47 @@ +from __future__ import unicode_literals + +from django.conf.urls import url + +from .views import ( + DocumentWebLinkListView, DocumentTypeWebLinksView, ResolvedWebLinkView, + SetupWebLinkDocumentTypesView, WebLinkCreateView, WebLinkDeleteView, + WebLinkEditView, WebLinkListView +) + +urlpatterns = [ + url( + regex=r'^document/(?P\d+)/list/$', + view=DocumentWebLinkListView.as_view(), + name='document_web_link_list' + ), + url( + regex=r'^document/(?P\d+)/(?P\d+)/$', + view=ResolvedWebLinkView.as_view(), name='web_link_instance_view' + ), + url( + regex=r'^document_types/(?P\d+)/web_links/$', + view=DocumentTypeWebLinksView.as_view(), + name='document_type_web_links' + ), + url( + regex=r'^setup/list/$', view=WebLinkListView.as_view(), + name='web_link_list' + ), + url( + regex=r'^setup/create/$', view=WebLinkCreateView.as_view(), + name='web_link_create' + ), + url( + regex=r'^setup/(?P\d+)/delete/$', + view=WebLinkDeleteView.as_view(), name='web_link_delete' + ), + url( + regex=r'^setup/(?P\d+)/edit/$', view=WebLinkEditView.as_view(), + name='web_link_edit' + ), + url( + regex=r'^setup/(?P\d+)/document_types/$', + view=SetupWebLinkDocumentTypesView.as_view(), + name='web_link_document_types' + ), +] diff --git a/mayan/apps/weblinks/views.py b/mayan/apps/weblinks/views.py new file mode 100644 index 0000000000..179bca93eb --- /dev/null +++ b/mayan/apps/weblinks/views.py @@ -0,0 +1,233 @@ +from __future__ import absolute_import, unicode_literals + +import logging + +from django.db import transaction +from django.shortcuts import get_object_or_404 +from django.template import RequestContext +from django.urls import reverse_lazy +from django.utils.translation import ugettext_lazy as _ +from django.views.generic import RedirectView + +from mayan.apps.acls.models import AccessControlList +from mayan.apps.common.generics import ( + AddRemoveView, SingleObjectCreateView, SingleObjectDeleteView, + SingleObjectEditView, SingleObjectListView +) +from mayan.apps.common.mixins import ExternalObjectMixin +from mayan.apps.documents.events import event_document_type_edited +from mayan.apps.documents.models import Document, DocumentType +from mayan.apps.documents.permissions import permission_document_type_edit + +from .events import event_web_link_edited +from .forms import WebLinkForm +from .icons import icon_web_link_setup +from .links import link_web_link_create +from .models import ResolvedWebLink, WebLink +from .permissions import ( + permission_web_link_create, permission_web_link_delete, + permission_web_link_edit, permission_web_link_instance_view, + permission_web_link_view +) + +logger = logging.getLogger(__name__) + + +class DocumentTypeWebLinksView(AddRemoveView): + main_object_method_add = 'web_link_add' + main_object_method_remove = 'web_link_remove' + main_object_permission = permission_document_type_edit + main_object_model = DocumentType + main_object_pk_url_kwarg = 'pk' + secondary_object_model = WebLink + secondary_object_permission = permission_web_link_edit + list_available_title = _('Available web links') + list_added_title = _('Web links enabled') + related_field = 'web_links' + + def action_add(self, queryset, _user): + with transaction.atomic(): + event_document_type_edited.commit( + actor=_user, target=self.main_object + ) + for obj in queryset: + self.main_object.web_links.add(obj) + event_web_link_edited.commit( + actor=_user, action_object=self.main_object, target=obj + ) + + def action_remove(self, queryset, _user): + with transaction.atomic(): + event_document_type_edited.commit( + actor=_user, target=self.main_object + ) + for obj in queryset: + self.main_object.web_links.remove(obj) + event_web_link_edited.commit( + actor=_user, action_object=self.main_object, target=obj + ) + + def get_actions_extra_kwargs(self): + return {'_user': self.request.user} + + def get_extra_context(self): + return { + 'object': self.main_object, + 'title': _( + 'Web links to enable for document type: %s' + ) % self.main_object, + } + + +class ResolvedWebLinkView(ExternalObjectMixin, RedirectView): + external_object_class = Document + external_object_pk_url_kwarg = 'document_pk' + external_object_permission = permission_web_link_instance_view + + def get_redirect_url(self, *args, **kwargs): + return self.get_resolved_web_link().get_url_for( + document=self.external_object + ) + + def get_resolved_web_link(self): + return get_object_or_404( + klass=self.get_web_link_queryset(), pk=self.kwargs['web_link_pk'] + ) + + def get_web_link_queryset(self): + return ResolvedWebLink.objects.get_for( + document=self.external_object, user=self.request.user + ) + + +class SetupWebLinkDocumentTypesView(AddRemoveView): + main_object_method_add = 'document_types_add' + main_object_method_remove = 'document_types_remove' + main_object_permission = permission_web_link_edit + main_object_model = WebLink + main_object_pk_url_kwarg = 'pk' + secondary_object_model = DocumentType + secondary_object_permission = permission_document_type_edit + list_available_title = _('Available document types') + list_added_title = _('Document types enabled') + related_field = 'document_types' + + def get_actions_extra_kwargs(self): + return {'_user': self.request.user} + + def get_extra_context(self): + return { + 'object': self.main_object, + 'title': _( + 'Document type for which to enable web link: %s' + ) % self.main_object, + } + + +class WebLinkListView(SingleObjectListView): + object_permission = permission_web_link_view + + def get_extra_context(self): + return { + 'hide_link': True, + 'hide_object': True, + 'no_results_icon': icon_web_link_setup, + 'no_results_main_link': link_web_link_create.resolve( + context=RequestContext(request=self.request) + ), + 'no_results_text': _( + 'Web links allow generating links from documents to external ' + 'resources.' + ), + 'no_results_title': _( + 'There are no web links' + ), + 'title': _('Web links'), + } + + def get_source_queryset(self): + return self.get_web_link_queryset() + + def get_web_link_queryset(self): + return WebLink.objects.all() + + +class DocumentWebLinkListView(WebLinkListView): + def dispatch(self, request, *args, **kwargs): + self.document = get_object_or_404(klass=Document, pk=self.kwargs['pk']) + + AccessControlList.objects.check_access( + obj=self.document, permissions=(permission_web_link_instance_view,), + user=request.user + ) + + return super( + DocumentWebLinkListView, self + ).dispatch(request, *args, **kwargs) + + def get_extra_context(self): + return { + 'document': self.document, + 'hide_link': True, + 'hide_object': True, + 'no_results_icon': icon_web_link_setup, + #'no_results_text': _( + # 'Web links allow defining relationships between ' + # 'documents even if they are in different indexes and ' + # 'are of different types.' + #), + 'no_results_title': _( + 'There are no web links for this document' + ), + 'object': self.document, + 'title': _('Web links for document: %s') % self.document, + } + + def get_web_link_queryset(self): + return ResolvedWebLink.objects.get_for( + document=self.document, user=self.request.user + ) + + +class WebLinkCreateView(SingleObjectCreateView): + extra_context = {'title': _('Create new web link')} + form_class = WebLinkForm + post_action_redirect = reverse_lazy( + viewname='weblinks:web_link_list' + ) + view_permission = permission_web_link_create + + def get_save_extra_data(self): + return {'_user': self.request.user} + + +class WebLinkDeleteView(SingleObjectDeleteView): + model = WebLink + object_permission = permission_web_link_delete + post_action_redirect = reverse_lazy( + viewname='weblinks:web_link_list' + ) + + def get_extra_context(self): + return { + 'object': self.get_object(), + 'title': _('Delete web link: %s') % self.get_object() + } + + +class WebLinkEditView(SingleObjectEditView): + form_class = WebLinkForm + model = WebLink + object_permission = permission_web_link_edit + post_action_redirect = reverse_lazy( + viewname='weblinks:web_link_list' + ) + + def get_extra_context(self): + return { + 'object': self.get_object(), + 'title': _('Edit web link: %s') % self.get_object() + } + + def get_save_extra_data(self): + return {'_user': self.request.user} diff --git a/mayan/settings/base.py b/mayan/settings/base.py index 3ec88a5322..3a550fbb6e 100644 --- a/mayan/settings/base.py +++ b/mayan/settings/base.py @@ -129,6 +129,7 @@ INSTALLED_APPS = ( 'mayan.apps.sources', 'mayan.apps.storage', 'mayan.apps.tags', + 'mayan.apps.weblinks', # Placed after rest_api to allow template overriding 'drf_yasg', )