diff options
-rw-r--r-- | archaeological_context_records/models.py | 10 | ||||
-rw-r--r-- | archaeological_context_records/urls.py | 7 | ||||
-rw-r--r-- | archaeological_files/models.py | 35 | ||||
-rw-r--r-- | archaeological_files/urls.py | 9 | ||||
-rw-r--r-- | archaeological_finds/models_finds.py | 8 | ||||
-rw-r--r-- | archaeological_finds/urls.py | 7 | ||||
-rw-r--r-- | archaeological_operations/models.py | 20 | ||||
-rw-r--r-- | archaeological_operations/tests.py | 24 | ||||
-rw-r--r-- | archaeological_operations/urls.py | 13 | ||||
-rw-r--r-- | archaeological_warehouse/models.py | 19 | ||||
-rw-r--r-- | archaeological_warehouse/urls.py | 13 | ||||
-rw-r--r-- | ishtar_common/forms_common.py | 30 | ||||
-rw-r--r-- | ishtar_common/views.py | 22 |
13 files changed, 198 insertions, 19 deletions
diff --git a/archaeological_context_records/models.py b/archaeological_context_records/models.py index 1bb09717d..21cc507c1 100644 --- a/archaeological_context_records/models.py +++ b/archaeological_context_records/models.py @@ -795,6 +795,13 @@ class ContextRecord( "archaeological_context_records.change_own_contextrecord" ], ) + QA_LINK = QuickAction( + url="contextrecord-qa-link", + icon_class="fa fa-link", + text=_("Link to account"), + target="many", + rights=["ishtaradmin"], + ) QA_EDIT = QuickAction( url="contextrecord-qa-bulk-update", icon_class="fa fa-pencil", @@ -807,7 +814,6 @@ class ContextRecord( ) QUICK_ACTIONS = [ QA_EDIT, - QA_LOCK, QuickAction( url="contextrecord-qa-duplicate", icon_class="fa fa-clone", @@ -818,6 +824,8 @@ class ContextRecord( "archaeological_context_records.change_own_contextrecord" ], ), + QA_LOCK, + QA_LINK, ] SERIALIZE_EXCLUDE = MainItem.SERIALIZE_EXCLUDE + ["contextrecord"] SERIALIZE_PROPERTIES = MainItem.SERIALIZE_PROPERTIES + [ diff --git a/archaeological_context_records/urls.py b/archaeological_context_records/urls.py index 338f5bb2a..c4d6e05bc 100644 --- a/archaeological_context_records/urls.py +++ b/archaeological_context_records/urls.py @@ -21,6 +21,7 @@ from django.conf.urls import url from django.urls import path from ishtar_common.utils import check_permissions +from ishtar_common.views import QALinkView from archaeological_context_records import models, views, views_api # be careful: each check_permissions must be relevant with ishtar_menu @@ -177,6 +178,12 @@ urlpatterns = [ kwargs={"model": models.ContextRecord}, ), url( + r"^contextrecord-qa-link/(?P<pks>[0-9-]+)?/$", + QALinkView.as_view(), + name="contextrecord-qa-link", + kwargs={"model": models.ContextRecord, "url": "contextrecord-qa-link"}, + ), + url( r"^contextrecord-qa-duplicate/(?P<pks>[0-9-]+)?/$", check_permissions(["archaeological_context_records.change_contextrecord", "archaeological_context_records.change_own_contextrecord"])( diff --git a/archaeological_files/models.py b/archaeological_files/models.py index b3815c95d..04481889f 100644 --- a/archaeological_files/models.py +++ b/archaeological_files/models.py @@ -45,26 +45,27 @@ from ishtar_common.utils import ( ) from ishtar_common.models import ( + BaseHistorizedItem, + CompleteIdentifierItem, + DashboardFormItem, Department, + Document, + DocumentItem, GeneralType, GlobalVar, - BaseHistorizedItem, - Imported, - OwnPerms, - Person, - Organization, - Town, - DashboardFormItem, HistoricalRecords, - ValueGetter, + HistoryModel, + Imported, MainItem, OperationType, + Organization, + OwnPerms, + Person, post_save_cache, - Document, - HistoryModel, + QuickAction, SearchVectorConfig, - DocumentItem, - CompleteIdentifierItem, + Town, + ValueGetter, ) from archaeological_operations.models import ( @@ -619,6 +620,16 @@ class File( HISTORICAL_M2M = ["towns", "departments"] SERIALIZE_PROPERTIES = ["external_id"] + QA_LINK = QuickAction( + url="file-qa-link", + icon_class="fa fa-link", + text=_("Link to account"), + target="many", + rights=["ishtaradmin"], + ) + QUICK_ACTIONS = [ + QA_LINK + ] # fields year = models.IntegerField(_("Year"), default=get_current_year) diff --git a/archaeological_files/urls.py b/archaeological_files/urls.py index 4b50047a6..4c278e0be 100644 --- a/archaeological_files/urls.py +++ b/archaeological_files/urls.py @@ -21,7 +21,8 @@ from django.conf.urls import url from django.urls import path from ishtar_common.utils import check_permissions -from archaeological_files import views, views_api +from ishtar_common.views import QALinkView +from archaeological_files import views, views_api, models from archaeological_operations.views import administrativeactfile_document # be carreful: each check_permissions must be relevant with ishtar_menu @@ -29,6 +30,12 @@ from archaeological_operations.views import administrativeactfile_document # forms: urlpatterns = [ url( + r"^file-qa-link/(?P<pks>[0-9-]+)?/$", + QALinkView.as_view(), + name="file-qa-link", + kwargs={"model": models.File, "url": "file-qa-link"}, + ), + url( r"file_administrativeactfile_search/(?P<step>.+)?$", check_permissions(["archaeological_operations.change_administrativeact"])( views.file_administrativeactfile_search_wizard diff --git a/archaeological_finds/models_finds.py b/archaeological_finds/models_finds.py index ece7d08b8..e224dc48c 100644 --- a/archaeological_finds/models_finds.py +++ b/archaeological_finds/models_finds.py @@ -1867,6 +1867,13 @@ class Find( rights=["archaeological_finds.change_find", "archaeological_finds.change_own_find"], ) + QA_LINK = QuickAction( + url="find-qa-link", + icon_class="fa fa-link", + text=_("Link to account"), + target="many", + rights=["ishtaradmin"], + ) QA_LOCK = QuickAction( url="find-qa-lock", icon_class="fa fa-lock", @@ -1921,6 +1928,7 @@ class Find( is_popup=False, ), QA_LOCK, + QA_LINK ] UP_MODEL_QUERY = { "operation": ( diff --git a/archaeological_finds/urls.py b/archaeological_finds/urls.py index ba10750d2..c7d8356ce 100644 --- a/archaeological_finds/urls.py +++ b/archaeological_finds/urls.py @@ -22,6 +22,7 @@ from django.urls import path from ishtar_common.utils import check_permissions, get_urls_for_model +from ishtar_common.views import QALinkView from archaeological_finds import views from archaeological_finds import views_api from archaeological_operations.views import administrativeactfile_document @@ -275,6 +276,12 @@ urlpatterns = [ kwargs={"model": models.Find}, ), url( + r"^find-qa-link/(?P<pks>[0-9-]+)?/$", + QALinkView.as_view(), + name="find-qa-link", + kwargs={"model": models.Find, "url": "find-qa-link"}, + ), + url( r"^treatment_creation/(?P<step>.+)?$", check_permissions( ["archaeological_finds.change_find", diff --git a/archaeological_operations/models.py b/archaeological_operations/models.py index 9e43f264b..debc26d8b 100644 --- a/archaeological_operations/models.py +++ b/archaeological_operations/models.py @@ -584,6 +584,13 @@ class ArchaeologicalSite( "archaeological_operations.change_own_archaeologicalsite" ], ) + QA_LINK = QuickAction( + url="site-qa-link", + icon_class="fa fa-link", + text=_("Link to account"), + target="many", + rights=["ishtaradmin"], + ) QA_EDIT = QuickAction( url="site-qa-bulk-update", icon_class="fa fa-pencil", @@ -596,7 +603,6 @@ class ArchaeologicalSite( ) QUICK_ACTIONS = [ QA_EDIT, - QA_LOCK, QuickAction( url="site-add-operation", icon_class="fa fa-plus", @@ -615,6 +621,8 @@ class ArchaeologicalSite( "archaeological_operations.change_own_archaeologicalsite" ], ), + QA_LOCK, + QA_LINK ] objects = SiteManager() @@ -1478,9 +1486,15 @@ class Operation( "archaeological_operations.change_own_operation" ], ) + QA_LINK = QuickAction( + url="operation-qa-link", + icon_class="fa fa-link", + text=_("Link to account"), + target="many", + rights=["ishtaradmin"], + ) QUICK_ACTIONS = [ QA_EDIT, - QA_LOCK, QuickAction( url="operation-qa-duplicate", icon_class="fa fa-clone", @@ -1491,6 +1505,8 @@ class Operation( "archaeological_operations.change_own_operation" ], ), + QA_LOCK, + QA_LINK, ] UP_MODEL_QUERY = { diff --git a/archaeological_operations/tests.py b/archaeological_operations/tests.py index 18d927d06..41d4a8611 100644 --- a/archaeological_operations/tests.py +++ b/archaeological_operations/tests.py @@ -4784,6 +4784,30 @@ class OperationQATest(OperationInitTest, TestCase): Permission.objects.get(codename="change_operation") ) + def test_link(self): + c = Client() + op0, op1 = self.operations[0], self.operations[1] + pks = "{}-{}".format(op0.pk, op1.pk) + url = reverse("operation-qa-link", args=[pks]) + + response = c.get(url) + self.assertEqual(response.status_code, 404) + + c.login(username=self.username, password=self.password) + response = c.get(reverse("operation-qa-link", args=[pks])) + + self.assertEqual(response.status_code, 200) + q_link = models.Operation.objects.filter(ishtar_users__pk__isnull=False) + self.assertEqual(q_link.count(), 0) + + response = c.post(url, {"action": "link", "account": self.user.pk}) + self.assertRedirects(response, "/success/") + self.assertEqual(q_link.count(), 2) + + response = c.post(url, {"action": "unlink", "account": self.user.pk}) + self.assertRedirects(response, "/success/") + self.assertEqual(q_link.count(), 0) + def test_lock(self): c = Client() op0, op1 = self.operations[0], self.operations[1] diff --git a/archaeological_operations/urls.py b/archaeological_operations/urls.py index ba96c64b2..29b68a349 100644 --- a/archaeological_operations/urls.py +++ b/archaeological_operations/urls.py @@ -21,6 +21,7 @@ from django.conf.urls import url from django.urls import path, register_converter from ishtar_common import urls_converters +from ishtar_common.views import QALinkView from ishtar_common.utils import check_permissions from archaeological_operations import views from archaeological_operations import views_api @@ -394,6 +395,12 @@ urlpatterns = [ kwargs={"model": models.Operation}, ), url( + r"^operation-qa-link/(?P<pks>[0-9-]+)?/$", + QALinkView.as_view(), + name="operation-qa-link", + kwargs={"model": models.Operation, "url": "operation-qa-link"}, + ), + url( r"^site-qa-duplicate/(?P<pks>[0-9-]+)?/$", check_permissions( ["archaeological_operations.change_archaeologicalsite", @@ -408,6 +415,12 @@ urlpatterns = [ kwargs={"model": models.ArchaeologicalSite}, ), url( + r"^site-qa-link/(?P<pks>[0-9-]+)?/$", + QALinkView.as_view(), + name="site-qa-link", + kwargs={"model": models.ArchaeologicalSite, "url": "site-qa-link"}, + ), + url( r"^site-qa-bulk-update/(?P<pks>[0-9-]+)?/$", check_permissions( ["archaeological_operations.change_archaeologicalsite", diff --git a/archaeological_warehouse/models.py b/archaeological_warehouse/models.py index 5a854c079..099d6a641 100644 --- a/archaeological_warehouse/models.py +++ b/archaeological_warehouse/models.py @@ -394,9 +394,17 @@ class Warehouse( "archaeological_warehouse.change_own_warehouse" ], ) + QA_LINK = QuickAction( + url="warehouse-qa-link", + icon_class="fa fa-link", + text=_("Link to account"), + target="many", + rights=["ishtaradmin"], + ) QUICK_ACTIONS = [ - QA_LOCK, QA_EDIT, + QA_LOCK, + QA_LINK ] objects = UUIDModelManager() @@ -1137,7 +1145,14 @@ class Container( "archaeological_warehouse.change_own_container" ], ) - QUICK_ACTIONS = [QA_EDIT, QA_MOVE, QA_LOCK] + QA_LINK = QuickAction( + url="container-qa-link", + icon_class="fa fa-link", + text=_("Link to account"), + target="many", + rights=["ishtaradmin"], + ) + QUICK_ACTIONS = [QA_EDIT, QA_MOVE, QA_LOCK, QA_LINK] BASE_QUERY_LOCATION = "container_tree_child__container_parent" SERIALIZE_CALL = { diff --git a/archaeological_warehouse/urls.py b/archaeological_warehouse/urls.py index 669732a57..78bc5945c 100644 --- a/archaeological_warehouse/urls.py +++ b/archaeological_warehouse/urls.py @@ -21,6 +21,7 @@ from django.conf.urls import url from django.urls import path from ishtar_common.utils import check_permissions +from ishtar_common.views import QALinkView from archaeological_warehouse import models, views, views_api @@ -150,6 +151,12 @@ urlpatterns = [ kwargs={"model": models.Warehouse}, ), url( + r"^warehouse-qa-link/(?P<pks>[0-9-]+)?/$", + QALinkView.as_view(), + name="warehouse-qa-link", + kwargs={"model": models.Warehouse, "url": "warehouse-qa-link"}, + ), + url( r"^warehouse-qa-bulk-update/(?P<pks>[0-9-]+)?/$", check_permissions([ "archaeological_warehouse.change_warehouse", @@ -248,6 +255,12 @@ urlpatterns = [ kwargs={"model": models.Container}, ), url( + r"^container-qa-link/(?P<pks>[0-9-]+)?/$", + QALinkView.as_view(), + name="container-qa-link", + kwargs={"model": models.Container, "url": "container-qa-link"}, + ), + url( r"container-merge/(?:(?P<page>\d+)/)?$", views.container_merge, name="container_merge", diff --git a/ishtar_common/forms_common.py b/ishtar_common/forms_common.py index 734707419..e7e6a334d 100644 --- a/ishtar_common/forms_common.py +++ b/ishtar_common/forms_common.py @@ -2833,6 +2833,36 @@ class QALockForm(forms.Form): item.save() +class QALinkForm(forms.Form): + action = forms.ChoiceField( + label=_("Action"), + choices=(("link", _("Link items")), ("unlink", _("Unlink items"))) + ) + account = forms.IntegerField( + widget=widgets.JQueryAutoComplete( + reverse_lazy( + 'autocomplete-user', + ), + associated_model=User), + label=_("User")) + + def __init__(self, *args, **kwargs): + self.items = kwargs.pop("items") + super().__init__(*args, **kwargs) + + def save(self, items, user): + try: + ishtar_user = models.IshtarUser.objects.get(pk=self.cleaned_data["account"]) + except models.IshtarUser.DoesNotExist: + return + if self.cleaned_data["action"] == "link": + for item in items: + item.ishtar_users.add(ishtar_user) + else: + for item in items: + item.ishtar_users.remove(ishtar_user) + + class SourceDeletionForm(FinalForm): confirm_msg = " " confirm_end_msg = _("Would you like to delete this documentation?") diff --git a/ishtar_common/views.py b/ishtar_common/views.py index f01e848a0..03b029fe2 100644 --- a/ishtar_common/views.py +++ b/ishtar_common/views.py @@ -3121,7 +3121,10 @@ class QAItemForm(IshtarMixin, LoginRequiredMixin, FormView): def pre_dispatch(self, request, *args, **kwargs): if not self.model: - raise NotImplementedError("No attribute model defined.") + if "model" in kwargs: + self.model = kwargs["model"] + else: + raise NotImplementedError("No attribute model defined.") pks = [int(pk) for pk in kwargs.get("pks").split("-")] self.items = list(self.model.objects.filter(pk__in=pks)) if not self.items: @@ -3252,6 +3255,23 @@ class QABaseLockView(QAItemForm): return HttpResponseRedirect(reverse("success")) +class QALinkView(QAItemForm): + form_class = forms.QALinkForm + page_name = _("Link items") + icon = "fa fa-link" + + def pre_dispatch(self, request, *args, **kwargs): + self.base_url = kwargs["url"] + super().pre_dispatch(request, *args, **kwargs) + if not request.user.ishtaruser.is_ishtaradmin: + url = reverse("qa-not-available") + return HttpResponseRedirect(url) + + def form_valid(self, form): + form.save(self.items, self.request.user) + return HttpResponseRedirect(reverse("success")) + + class QAOrganizationForm(QAItemEditForm): model = models.Organization form_class = forms.QAOrganizationFormMulti |