clinicedc 2.0.38__py3-none-any.whl → 2.0.40__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of clinicedc might be problematic. Click here for more details.
- {clinicedc-2.0.38.dist-info → clinicedc-2.0.40.dist-info}/METADATA +3 -12
- {clinicedc-2.0.38.dist-info → clinicedc-2.0.40.dist-info}/RECORD +146 -153
- {clinicedc-2.0.38.dist-info → clinicedc-2.0.40.dist-info}/WHEEL +1 -1
- edc_adverse_event/dashboard_urls.py +2 -0
- edc_adverse_event/middleware.py +7 -6
- edc_adverse_event/navbars.py +4 -8
- edc_adverse_event/templates/edc_adverse_event/tmg/tmg_ae_listboard_result.html +27 -23
- edc_adverse_event/templatetags/edc_adverse_event_extras.py +21 -34
- edc_adverse_event/urls.py +14 -6
- edc_adverse_event/view_mixins/ae/ae_listboard_view_mixin.py +6 -8
- edc_adverse_event/view_mixins/ae/death_report_listboard_view_mixin.py +2 -4
- edc_adverse_event/view_mixins/tmg/tmg_ae_listboard_view_mixin.py +9 -7
- edc_adverse_event/views/home_view.py +1 -2
- edc_adverse_event/views/tmg/death_listboard_view.py +8 -6
- edc_adverse_event/views/tmg/home_view.py +4 -3
- edc_adverse_event/views/tmg/summary_listboard_view.py +4 -4
- edc_appointment/utils.py +3 -6
- edc_appointment/views/unscheduled_appointment_view.py +1 -1
- edc_consent/form_validators/consent_definition_form_validator_mixin.py +5 -2
- edc_consent/model_mixins/consent_version_model_mixin.py +1 -1
- edc_consent/navbars.py +2 -1
- edc_crf/model_mixins/crf_model_mixin.py +5 -1
- edc_crf/model_mixins/crf_no_manager_model_mixin.py +2 -2
- edc_crf/model_mixins/singleton_crf_model_mixin.py +1 -1
- edc_dashboard/middleware.py +10 -16
- edc_dashboard/middleware_mixins.py +10 -0
- edc_dashboard/navbars.py +1 -1
- edc_dashboard/url_config.py +50 -31
- edc_dashboard/url_names.py +23 -17
- edc_dashboard/utils.py +4 -4
- edc_dashboard/view_mixins/template_request_context_mixin.py +5 -8
- edc_dashboard/view_mixins/url_request_context_mixin.py +38 -26
- edc_dashboard/views/administration_view.py +2 -2
- edc_dashboard/views/dashboard_view.py +5 -10
- edc_data_manager/handlers/handlers.py +17 -5
- edc_data_manager/models/query_rule.py +7 -7
- edc_data_manager/navbar_item.py +1 -1
- edc_data_manager/rule/query_rule_wrapper.py +1 -1
- edc_data_manager/rule/rule_runner.py +6 -6
- edc_device/navbars.py +1 -1
- edc_export/navbars.py +2 -2
- edc_glucose/model_mixin_factories/fasting_model_mixin_factory.py +1 -1
- edc_identifier/identifier.py +6 -9
- edc_lab_dashboard/dashboard_urls.py +7 -5
- edc_lab_dashboard/middleware.py +10 -17
- edc_lab_dashboard/navbars.py +9 -9
- edc_lab_dashboard/templates/edc_lab_dashboard/listboard/tags/status_column.html +7 -0
- edc_lab_dashboard/urls.py +2 -5
- edc_lab_dashboard/view_mixins/form_action_view_mixin.py +1 -2
- edc_lab_dashboard/views/action_views/action_view.py +6 -6
- edc_lab_dashboard/views/action_views/aliquot_view.py +1 -1
- edc_lab_dashboard/views/action_views/manage_box_item_view.py +2 -3
- edc_lab_dashboard/views/action_views/manage_manifest_view.py +1 -1
- edc_lab_dashboard/views/action_views/manifest_view.py +2 -2
- edc_lab_dashboard/views/action_views/pack_view.py +2 -2
- edc_lab_dashboard/views/action_views/process_view.py +1 -1
- edc_lab_dashboard/views/action_views/receive_view.py +1 -1
- edc_lab_dashboard/views/action_views/requisition_view.py +1 -1
- edc_lab_dashboard/views/action_views/verify_box_item_view.py +1 -1
- edc_lab_dashboard/views/listboard_views/manage_box_listboard_view.py +4 -5
- edc_lab_dashboard/views/listboard_views/manifest_listboard_view.py +5 -6
- edc_lab_dashboard/views/listboard_views/process_listboard_view.py +4 -5
- edc_lab_dashboard/views/listboard_views/receive_listboard_view.py +5 -6
- edc_lab_dashboard/views/listboard_views/verify_box_listboard_view.py +5 -6
- edc_label/navbars.py +1 -1
- edc_list_data/admin.py +3 -3
- edc_list_data/load_model_data.py +1 -1
- edc_list_data/management/commands/load_list_data.py +2 -2
- edc_list_data/site_list_data.py +4 -4
- edc_listboard/middleware.py +9 -8
- edc_listboard/templates/edc_listboard/listboard.html +1 -1
- edc_listboard/view_mixins/listboard_filter_view_mixin.py +1 -1
- edc_listboard/view_mixins/search_form_view_mixin.py +1 -1
- edc_listboard/views/listboard_view.py +16 -25
- edc_listboard/views/screen/screening_listboard_view.py +2 -2
- edc_listboard/views/subject/subject_listboard_view.py +2 -2
- edc_locator/forms/subject_locator_form_validator.py +2 -2
- edc_ltfu/action_items.py +1 -2
- edc_ltfu/forms/ltfu_form_validator_mixin.py +3 -3
- edc_ltfu/modeladmin_mixin.py +1 -1
- edc_ltfu/modelform_mixins.py +2 -2
- edc_metadata/admin/modeladmin_mixins.py +11 -9
- edc_metadata/management/commands/update_metadata.py +1 -1
- edc_metadata/management/commands/update_metadata_schedule_names.py +7 -7
- edc_metadata/management/commands/validate_entry_status.py +1 -1
- edc_metadata/management/commands/validate_rule_groups.py +1 -1
- edc_metadata/metadata/metadata_getter.py +3 -5
- edc_metadata/metadata_handler.py +5 -5
- edc_metadata/metadata_mixins/source_model_metadata_mixin.py +1 -1
- edc_metadata/metadata_refresher.py +1 -1
- edc_metadata/metadata_rules/crf/crf_rule.py +1 -1
- edc_metadata/metadata_rules/logic.py +3 -3
- edc_metadata/metadata_rules/persistant_singleton_mixin.py +2 -4
- edc_metadata/metadata_rules/requisition/requisition_rule_group.py +1 -1
- edc_metadata/metadata_rules/rule.py +4 -3
- edc_metadata/metadata_rules/rule_group.py +2 -2
- edc_metadata/metadata_rules/rule_group_meta_options.py +2 -2
- edc_metadata/metadata_rules/rule_group_metaclass.py +21 -22
- edc_metadata/metadata_rules/site.py +1 -1
- edc_metadata/metadata_updater.py +4 -3
- edc_metadata/model_mixins/creates/creates_metadata_model_mixin.py +3 -5
- edc_metadata/model_mixins/updates/updates_metadata_model_mixin.py +1 -1
- edc_metadata/next_form_getter.py +15 -19
- edc_metadata/offline_models.py +1 -1
- edc_metadata/requisition/requisition_metadata_handler.py +5 -5
- edc_metadata/update_metadata_on_schedule_change.py +2 -4
- edc_metadata/utils.py +1 -1
- edc_model/models/signals.py +7 -2
- edc_model_admin/mixins/model_admin_redirect_on_delete_mixin.py +4 -3
- edc_navbar/apps.py +0 -2
- edc_navbar/navbar.py +1 -1
- edc_navbar/navbar_item.py +29 -16
- edc_navbar/navbars.py +6 -19
- edc_navbar/site_navbars.py +6 -7
- edc_navbar/system_checks.py +3 -10
- edc_navbar/utils.py +14 -0
- edc_navbar/view_mixin.py +6 -9
- edc_pharmacy/navbars.py +1 -1
- edc_pharmacy/views/confirm_stock_from_queryset_view.py +3 -3
- edc_protocol/middleware.py +9 -13
- edc_protocol/navbars.py +1 -1
- edc_refusal/forms.py +1 -3
- edc_reportable/utils/convert_units.py +1 -1
- edc_review_dashboard/middleware.py +6 -3
- edc_review_dashboard/navbars.py +1 -2
- edc_review_dashboard/urls.py +3 -2
- edc_review_dashboard/views/subject_review_listboard_view.py +4 -2
- edc_subject_dashboard/dashboard_templates.py +1 -3
- edc_subject_dashboard/dashboard_urls.py +8 -0
- edc_subject_dashboard/middleware.py +10 -7
- edc_subject_dashboard/templates/edc_subject_dashboard/buttons/refresh_appointments_button.html +1 -1
- edc_subject_dashboard/templates/edc_subject_dashboard/dashboard.html +1 -1
- edc_subject_dashboard/templatetags/edc_subject_dashboard_extras.py +3 -1
- edc_subject_dashboard/urls.py +13 -4
- edc_subject_dashboard/views/base_requisition_view.py +2 -1
- edc_subject_dashboard/views/subject_dashboard_view.py +1 -2
- edc_timepoint/__init__.py +0 -2
- edc_timepoint/model_mixins.py +1 -2
- edc_timepoint/utils.py +1 -1
- edc_timepoint/visit_timepoint_lookup.py +6 -0
- edc_visit_schedule/admin/subject_schedule_history_admin.py +1 -2
- edc_visit_schedule/navbars.py +3 -4
- edc_visit_schedule/visit/visit.py +15 -0
- edc_visit_tracking/model_mixins/visit_model_mixin/visit_model_mixin.py +5 -0
- edc_visit_tracking/models/subject_visit.py +5 -0
- edc_lab_dashboard/model_wrappers/__init__.py +0 -8
- edc_lab_dashboard/model_wrappers/aliquot_model_wrapper.py +0 -31
- edc_lab_dashboard/model_wrappers/base_box_item_model_wrapper.py +0 -21
- edc_lab_dashboard/model_wrappers/box_model_wrapper.py +0 -12
- edc_lab_dashboard/model_wrappers/manage_box_item_model_wrapper.py +0 -6
- edc_lab_dashboard/model_wrappers/manifest_item_model_wrapper.py +0 -21
- edc_lab_dashboard/model_wrappers/manifest_model_wrapper.py +0 -11
- edc_lab_dashboard/model_wrappers/requisition_model_wrapper.py +0 -25
- edc_lab_dashboard/model_wrappers/result_model_wrapper.py +0 -8
- edc_lab_dashboard/model_wrappers/verify_box_model_wrapper.py +0 -10
- edc_navbar/get_default_navbar.py +0 -9
- {clinicedc-2.0.38.dist-info → clinicedc-2.0.40.dist-info}/licenses/LICENSE +0 -0
edc_navbar/view_mixin.py
CHANGED
|
@@ -1,14 +1,12 @@
|
|
|
1
1
|
from typing import Any
|
|
2
2
|
|
|
3
|
-
from django.apps import apps as django_apps
|
|
4
|
-
|
|
5
|
-
from .get_default_navbar import get_default_navbar
|
|
6
3
|
from .site_navbars import site_navbars
|
|
4
|
+
from .utils import get_default_navbar_name
|
|
7
5
|
|
|
8
6
|
|
|
9
7
|
class NavbarViewMixin:
|
|
10
8
|
navbar_selected_item = None
|
|
11
|
-
navbar_name =
|
|
9
|
+
navbar_name = get_default_navbar_name()
|
|
12
10
|
|
|
13
11
|
def get_context_data(self, **kwargs) -> dict[str, Any]:
|
|
14
12
|
"""Add rendered navbar <navbar_name> to the context for
|
|
@@ -16,18 +14,17 @@ class NavbarViewMixin:
|
|
|
16
14
|
|
|
17
15
|
Also adds the "default" navbar.
|
|
18
16
|
"""
|
|
19
|
-
kwargs = self.
|
|
17
|
+
kwargs = self.get_context_data_for_navbars(kwargs)
|
|
20
18
|
return super().get_context_data(**kwargs)
|
|
21
19
|
|
|
22
20
|
def get_navbar_name(self):
|
|
23
21
|
return self.navbar_name
|
|
24
22
|
|
|
25
|
-
def
|
|
23
|
+
def get_context_data_for_navbars(self, context) -> dict:
|
|
26
24
|
navbar = site_navbars.get_navbar(name=self.get_navbar_name())
|
|
27
25
|
navbar.set_active(self.get_navbar_selected(**context))
|
|
28
26
|
context.update(navbar=navbar)
|
|
29
|
-
|
|
30
|
-
default_navbar_name = app_config.default_navbar_name
|
|
27
|
+
default_navbar_name = get_default_navbar_name()
|
|
31
28
|
if default_navbar_name and self.get_navbar_name() != default_navbar_name:
|
|
32
29
|
default_navbar = site_navbars.get_navbar(name=default_navbar_name)
|
|
33
30
|
default_navbar.set_active(self.navbar_selected_item)
|
|
@@ -36,5 +33,5 @@ class NavbarViewMixin:
|
|
|
36
33
|
)
|
|
37
34
|
return context
|
|
38
35
|
|
|
39
|
-
def get_navbar_selected(self, **kwargs) -> str:
|
|
36
|
+
def get_navbar_selected(self, **kwargs) -> str: # noqa: ARG002
|
|
40
37
|
return self.navbar_selected_item
|
edc_pharmacy/navbars.py
CHANGED
|
@@ -9,7 +9,6 @@ from django.urls import reverse
|
|
|
9
9
|
from django.utils.decorators import method_decorator
|
|
10
10
|
from django.utils.translation import gettext as _
|
|
11
11
|
from django.views.generic.base import TemplateView
|
|
12
|
-
|
|
13
12
|
from edc_constants.constants import CONFIRMED
|
|
14
13
|
from edc_dashboard.view_mixins import EdcViewMixin
|
|
15
14
|
from edc_navbar import NavbarViewMixin
|
|
@@ -29,8 +28,8 @@ class ConfirmStockFromQuerySetView(
|
|
|
29
28
|
navbar_selected_item = "pharmacy"
|
|
30
29
|
codes_per_page = 12
|
|
31
30
|
|
|
32
|
-
def get_context_data(self, **kwargs):
|
|
33
|
-
|
|
31
|
+
def get_context_data(self, **kwargs):
|
|
32
|
+
kwargs.update(
|
|
34
33
|
CONFIRMED=CONFIRMED,
|
|
35
34
|
ALREADY_CONFIRMED=ALREADY_CONFIRMED,
|
|
36
35
|
INVALID=INVALID,
|
|
@@ -40,6 +39,7 @@ class ConfirmStockFromQuerySetView(
|
|
|
40
39
|
source_changelist_url=self.source_changelist_url,
|
|
41
40
|
**self.session_data,
|
|
42
41
|
)
|
|
42
|
+
return super().get_context_data(**kwargs)
|
|
43
43
|
|
|
44
44
|
@property
|
|
45
45
|
def session_data(self):
|
edc_protocol/middleware.py
CHANGED
|
@@ -8,18 +8,14 @@ class ResearchProtocolConfigMiddleware:
|
|
|
8
8
|
def __call__(self, request):
|
|
9
9
|
return self.get_response(request)
|
|
10
10
|
|
|
11
|
-
def process_view(self, request, *args):
|
|
12
|
-
pass
|
|
13
|
-
|
|
14
11
|
def process_template_response(self, request, response): # noqa: ARG002
|
|
15
|
-
if
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
)
|
|
12
|
+
if getattr(response, "context_data", None):
|
|
13
|
+
protocol_config = ResearchProtocolConfig()
|
|
14
|
+
response.context_data.update(
|
|
15
|
+
copyright=protocol_config.copyright,
|
|
16
|
+
disclaimer=protocol_config.disclaimer,
|
|
17
|
+
institution=protocol_config.institution,
|
|
18
|
+
license=protocol_config.license,
|
|
19
|
+
project_name=protocol_config.project_name,
|
|
20
|
+
)
|
|
25
21
|
return response
|
edc_protocol/navbars.py
CHANGED
edc_refusal/forms.py
CHANGED
|
@@ -2,7 +2,6 @@ from django import forms
|
|
|
2
2
|
from django.core.exceptions import ObjectDoesNotExist
|
|
3
3
|
from django.urls.base import reverse
|
|
4
4
|
from django.utils.html import format_html
|
|
5
|
-
|
|
6
5
|
from edc_constants.constants import OTHER
|
|
7
6
|
from edc_dashboard.url_names import url_names
|
|
8
7
|
from edc_form_validators import FormValidator, FormValidatorMixin
|
|
@@ -47,8 +46,7 @@ class AlreadyConsentedFormMixin:
|
|
|
47
46
|
kwargs={"subject_identifier": obj.subject_identifier},
|
|
48
47
|
)
|
|
49
48
|
msg = format_html(
|
|
50
|
-
|
|
51
|
-
'See subject <A href="{}">{}</A>',
|
|
49
|
+
'Not allowed. Subject has already consented. See subject <A href="{}">{}</A>',
|
|
52
50
|
url,
|
|
53
51
|
obj.subject_identifier,
|
|
54
52
|
)
|
|
@@ -1,24 +1,27 @@
|
|
|
1
1
|
import contextlib
|
|
2
2
|
|
|
3
3
|
from django.conf import settings
|
|
4
|
+
from edc_dashboard.middleware_mixins import EdcTemplateMiddlewareMixin
|
|
4
5
|
|
|
5
6
|
from .dashboard_templates import dashboard_templates
|
|
6
7
|
|
|
7
8
|
|
|
8
|
-
class DashboardMiddleware:
|
|
9
|
+
class DashboardMiddleware(EdcTemplateMiddlewareMixin):
|
|
9
10
|
def __init__(self, get_response):
|
|
10
11
|
self.get_response = get_response
|
|
11
12
|
|
|
12
13
|
def __call__(self, request):
|
|
14
|
+
self.check_for_required_request_attrs(request)
|
|
13
15
|
return self.get_response(request)
|
|
14
16
|
|
|
15
|
-
def process_view(self, request, *args) -> None:
|
|
17
|
+
def process_view(self, request, *args) -> None:
|
|
16
18
|
template_data = dashboard_templates
|
|
17
19
|
with contextlib.suppress(AttributeError):
|
|
18
20
|
template_data.update(settings.REVIEW_DASHBOARD_BASE_TEMPLATES)
|
|
19
21
|
request.template_data.update(**template_data)
|
|
20
22
|
|
|
21
23
|
def process_template_response(self, request, response):
|
|
22
|
-
if response
|
|
24
|
+
if getattr(response, "context_data", None):
|
|
23
25
|
response.context_data.update(**request.template_data)
|
|
26
|
+
request.template_data.update(**request.template_data)
|
|
24
27
|
return response
|
edc_review_dashboard/navbars.py
CHANGED
|
@@ -7,10 +7,9 @@ navbar_item = NavbarItem(
|
|
|
7
7
|
label="Review",
|
|
8
8
|
title="Subject Review",
|
|
9
9
|
codename="edc_review_dashboard.view_subject_review_listboard",
|
|
10
|
-
|
|
10
|
+
url_names_key="subject_review_listboard_url",
|
|
11
11
|
)
|
|
12
12
|
|
|
13
|
-
|
|
14
13
|
navbar.register(navbar_item)
|
|
15
14
|
|
|
16
15
|
site_navbars.register(navbar)
|
edc_review_dashboard/urls.py
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
from django.contrib import admin
|
|
2
2
|
from django.urls import path
|
|
3
|
-
|
|
4
3
|
from edc_data_manager.views import HomeView
|
|
5
4
|
from edc_protocol.research_protocol_config import ResearchProtocolConfig
|
|
6
5
|
|
|
@@ -10,7 +9,7 @@ app_name = "edc_review_dashboard"
|
|
|
10
9
|
|
|
11
10
|
urlpatterns = SubjectReviewListboardView.urls(
|
|
12
11
|
namespace=app_name,
|
|
13
|
-
|
|
12
|
+
url_names_key="subject_review_listboard_url",
|
|
14
13
|
identifier_pattern=ResearchProtocolConfig().subject_identifier_pattern,
|
|
15
14
|
)
|
|
16
15
|
|
|
@@ -18,3 +17,5 @@ urlpatterns += [
|
|
|
18
17
|
path("admin/", admin.site.urls),
|
|
19
18
|
path("", HomeView.as_view(), name="home_url"),
|
|
20
19
|
]
|
|
20
|
+
|
|
21
|
+
# aliquot_listboard = ("edc_lab_dashboard:aliquot_listboard_url",)
|
|
@@ -3,7 +3,6 @@ from __future__ import annotations
|
|
|
3
3
|
from typing import TYPE_CHECKING, Any
|
|
4
4
|
|
|
5
5
|
from django.db.models.aggregates import Count
|
|
6
|
-
|
|
7
6
|
from edc_appointment.view_mixins import AppointmentViewMixin
|
|
8
7
|
from edc_dashboard.url_names import url_names
|
|
9
8
|
from edc_dashboard.view_mixins import EdcViewMixin
|
|
@@ -44,6 +43,7 @@ class SubjectReviewListboardView(
|
|
|
44
43
|
|
|
45
44
|
listboard_template = "subject_review_listboard_template"
|
|
46
45
|
listboard_url = "subject_review_listboard_url"
|
|
46
|
+
listboard_back_url = "subject_review_listboard_url"
|
|
47
47
|
listboard_panel_style = "default"
|
|
48
48
|
listboard_panel_title = "Subject Review"
|
|
49
49
|
listboard_view_permission_codename = "edc_review_dashboard.view_subject_review_listboard"
|
|
@@ -51,6 +51,7 @@ class SubjectReviewListboardView(
|
|
|
51
51
|
navbar_selected_item = "subject_review"
|
|
52
52
|
ordering = ("subject_identifier", "visit_code", "visit_code_sequence")
|
|
53
53
|
paginate_by = 25
|
|
54
|
+
paginator_url = "subject_review_listboard_url"
|
|
54
55
|
search_form_url = "subject_review_listboard_url"
|
|
55
56
|
search_fields = (
|
|
56
57
|
"subject_identifier",
|
|
@@ -59,7 +60,8 @@ class SubjectReviewListboardView(
|
|
|
59
60
|
"user_modified",
|
|
60
61
|
)
|
|
61
62
|
|
|
62
|
-
#
|
|
63
|
+
# Attribute to call SubjectReviewListboardView.urls in urls.py
|
|
64
|
+
# See UrlRequestContextMixin and UrlConfig
|
|
63
65
|
urlconfig_getattr = "review_listboard_urls"
|
|
64
66
|
|
|
65
67
|
def get_context_data(self, **kwargs) -> dict[str, Any]:
|
|
@@ -1,25 +1,28 @@
|
|
|
1
1
|
from django.conf import settings
|
|
2
2
|
|
|
3
|
+
from edc_dashboard.middleware_mixins import EdcTemplateMiddlewareMixin
|
|
4
|
+
from edc_subject_dashboard.dashboard_urls import dashboard_urls
|
|
5
|
+
|
|
3
6
|
from .dashboard_templates import dashboard_templates
|
|
4
7
|
|
|
5
8
|
|
|
6
|
-
class DashboardMiddleware:
|
|
9
|
+
class DashboardMiddleware(EdcTemplateMiddlewareMixin):
|
|
7
10
|
def __init__(self, get_response):
|
|
8
11
|
self.get_response = get_response
|
|
9
12
|
|
|
10
13
|
def __call__(self, request):
|
|
14
|
+
self.check_for_required_request_attrs(request)
|
|
11
15
|
return self.get_response(request)
|
|
12
16
|
|
|
13
|
-
def process_view(self, request, *args):
|
|
17
|
+
def process_view(self, request, *args):
|
|
14
18
|
"""Adds/Updates references to templates."""
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
template_data = dashboard_templates
|
|
19
|
+
request.url_name_data.update(**dashboard_urls)
|
|
20
|
+
template_data = getattr(settings, "SUBJECT_DASHBOARD_BASE_TEMPLATES", {})
|
|
21
|
+
template_data.update(**dashboard_templates)
|
|
19
22
|
request.template_data.update(**template_data)
|
|
20
23
|
|
|
21
24
|
def process_template_response(self, request, response):
|
|
22
|
-
if response
|
|
25
|
+
if getattr(response, "context_data", None):
|
|
23
26
|
response.context_data.update(**request.url_name_data)
|
|
24
27
|
response.context_data.update(**request.template_data)
|
|
25
28
|
return response
|
edc_subject_dashboard/templates/edc_subject_dashboard/buttons/refresh_appointments_button.html
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
<a {% if url %}href="{{ url }}" {% else %} disabled {% endif %}data-toggle="tooltip" title="Refresh appointments" role="button" class="btn btn-sm btn-default"><i class="fas fa-arrows-rotate fa-1x fa-fw" aria-hidden="true"></i></a>
|
|
1
|
+
<a {% if url %}href="{{ url }}" {% else %} disabled {% endif %}data-toggle="tooltip" title="{{ title|default:"Refresh appointments" }}" role="button" class="btn btn-sm btn-default"><i class="fas fa-arrows-rotate fa-1x fa-fw" aria-hidden="true"></i></a>
|
|
@@ -481,10 +481,12 @@ def render_refresh_appointments_button(
|
|
|
481
481
|
visit_schedule_name: str | None = None,
|
|
482
482
|
schedule_name: str | None = None,
|
|
483
483
|
) -> dict:
|
|
484
|
+
title = "Refresh appointments"
|
|
484
485
|
if context["request"].user.userprofile.is_multisite_viewer or context[
|
|
485
486
|
"request"
|
|
486
487
|
].user.userprofile.roles.filter(name=AUDITOR_ROLE):
|
|
487
488
|
url = None
|
|
489
|
+
title = f"{title} (Disabled for Auditor)"
|
|
488
490
|
else:
|
|
489
491
|
url = reverse(
|
|
490
492
|
"edc_subject_dashboard:refresh_appointments_url",
|
|
@@ -494,7 +496,7 @@ def render_refresh_appointments_button(
|
|
|
494
496
|
schedule_name=schedule_name,
|
|
495
497
|
),
|
|
496
498
|
)
|
|
497
|
-
return dict(url=url)
|
|
499
|
+
return dict(url=url, title=title)
|
|
498
500
|
|
|
499
501
|
|
|
500
502
|
@register.inclusion_tag(
|
edc_subject_dashboard/urls.py
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
from django.urls.conf import path
|
|
2
|
-
|
|
3
2
|
from edc_dashboard.url_names import url_names
|
|
4
3
|
from edc_metadata.views import RefreshMetadataActionsView
|
|
5
4
|
|
|
@@ -37,6 +36,16 @@ urlpatterns = [
|
|
|
37
36
|
),
|
|
38
37
|
]
|
|
39
38
|
|
|
40
|
-
url_names.register(
|
|
41
|
-
|
|
42
|
-
|
|
39
|
+
url_names.register(
|
|
40
|
+
key="requisition_print_actions_url",
|
|
41
|
+
url="requisition_print_actions_url",
|
|
42
|
+
namespace=app_name,
|
|
43
|
+
)
|
|
44
|
+
url_names.register(
|
|
45
|
+
key="requisition_verify_actions_url",
|
|
46
|
+
url="requisition_verify_actions_url",
|
|
47
|
+
namespace=app_name,
|
|
48
|
+
)
|
|
49
|
+
url_names.register(
|
|
50
|
+
key="refresh_metadata_actions_url", url="refresh_metadata_actions_url", namespace=app_name
|
|
51
|
+
)
|
|
@@ -9,12 +9,13 @@ from edc_label.printers_mixin import PrintersMixin
|
|
|
9
9
|
|
|
10
10
|
class BaseRequisitionView(LoginRequiredMixin, PrintersMixin, View):
|
|
11
11
|
success_url_name = "subject_dashboard_url"
|
|
12
|
+
lab_home_url_name = "requisition_listboard_url"
|
|
12
13
|
|
|
13
14
|
def get_success_url(self):
|
|
14
15
|
return url_names.get(self.success_url_name)
|
|
15
16
|
|
|
16
17
|
def get(self, request, *args, **kwargs): # noqa: ARG002
|
|
17
|
-
url = reverse(
|
|
18
|
+
url = reverse(url_names.get(self.lab_home_url_name))
|
|
18
19
|
return HttpResponseRedirect(url)
|
|
19
20
|
|
|
20
21
|
def head(self, request, *args, **kwargs):
|
|
@@ -3,7 +3,6 @@ from __future__ import annotations
|
|
|
3
3
|
from typing import Any
|
|
4
4
|
|
|
5
5
|
from django.core.exceptions import ImproperlyConfigured
|
|
6
|
-
|
|
7
6
|
from edc_action_item.view_mixins import ActionItemViewMixin
|
|
8
7
|
from edc_appointment.view_mixins import AppointmentViewMixin
|
|
9
8
|
from edc_consent.view_mixins import ConsentViewMixin
|
|
@@ -44,7 +43,7 @@ class SubjectDashboardView(
|
|
|
44
43
|
navbar_selected_item = "consented_subject"
|
|
45
44
|
|
|
46
45
|
dashboard_url_name = "subject_dashboard_url"
|
|
47
|
-
|
|
46
|
+
dashboard_template_name = "subject_dashboard_template"
|
|
48
47
|
|
|
49
48
|
default_manager = "on_site"
|
|
50
49
|
|
edc_timepoint/__init__.py
CHANGED
edc_timepoint/model_mixins.py
CHANGED
|
@@ -32,8 +32,7 @@ class TimepointLookupModelMixin(models.Model):
|
|
|
32
32
|
timepoint_lookup_cls = TimepointLookup
|
|
33
33
|
|
|
34
34
|
def save(self, *args, **kwargs):
|
|
35
|
-
|
|
36
|
-
if timepoint_lookup_cls and get_enable_timepoint_checks():
|
|
35
|
+
if get_enable_timepoint_checks() and getattr(self, "timepoint_lookup_cls", None):
|
|
37
36
|
timepoint_lookup = self.timepoint_lookup_cls()
|
|
38
37
|
if timepoint_lookup.timepoint_model == self._meta.label_lower:
|
|
39
38
|
raise ImproperlyConfigured(
|
edc_timepoint/utils.py
CHANGED
|
@@ -3,7 +3,6 @@ from django.template.loader import render_to_string
|
|
|
3
3
|
from django.urls import NoReverseMatch, reverse
|
|
4
4
|
from django.utils.translation import gettext as _
|
|
5
5
|
from django_audit_fields import audit_fields, audit_fieldset_tuple
|
|
6
|
-
|
|
7
6
|
from edc_dashboard.url_names import url_names
|
|
8
7
|
from edc_model_admin.dashboard import ModelAdminSubjectDashboardMixin
|
|
9
8
|
from edc_sites.admin import SiteModelAdminMixin
|
|
@@ -100,7 +99,7 @@ class SubjectScheduleHistoryAdmin(
|
|
|
100
99
|
def review(obj=None) -> str:
|
|
101
100
|
try:
|
|
102
101
|
url = (
|
|
103
|
-
f"{reverse('
|
|
102
|
+
f"{reverse(url_names.get('subject_review_listboard_url'))}?"
|
|
104
103
|
f"q={obj.subject_identifier}"
|
|
105
104
|
)
|
|
106
105
|
except NoReverseMatch:
|
edc_visit_schedule/navbars.py
CHANGED
|
@@ -8,7 +8,7 @@ navbar.register(
|
|
|
8
8
|
title="Visit Schedule",
|
|
9
9
|
label="Visit Schedule",
|
|
10
10
|
fa_icon="fa-calendar",
|
|
11
|
-
|
|
11
|
+
url_with_namespace="edc_visit_schedule:home_url",
|
|
12
12
|
codename="edc_navbar.nav_visit_schedule",
|
|
13
13
|
)
|
|
14
14
|
)
|
|
@@ -19,9 +19,8 @@ navbar.register(
|
|
|
19
19
|
title="Subject History",
|
|
20
20
|
label="Subject History",
|
|
21
21
|
fa_icon="fa-history",
|
|
22
|
-
|
|
23
|
-
"
|
|
24
|
-
"edc_visit_schedule_subjectschedulehistory_changelist"
|
|
22
|
+
url_with_namespace=(
|
|
23
|
+
"edc_visit_schedule_admin:edc_visit_schedule_subjectschedulehistory_changelist"
|
|
25
24
|
),
|
|
26
25
|
codename="edc_navbar.nav_visit_schedule",
|
|
27
26
|
)
|
|
@@ -217,6 +217,14 @@ class Visit:
|
|
|
217
217
|
|
|
218
218
|
@property
|
|
219
219
|
def all_crfs(self) -> CrfCollection:
|
|
220
|
+
"""Return a new collection containing all crfs.
|
|
221
|
+
|
|
222
|
+
The new collection contains:
|
|
223
|
+
* crfs
|
|
224
|
+
* crfs_unscheduled
|
|
225
|
+
* crfs_prn
|
|
226
|
+
* crfs_missed
|
|
227
|
+
"""
|
|
220
228
|
crfs = list(self.crfs) + [
|
|
221
229
|
crf
|
|
222
230
|
for crf in self.crfs_unscheduled
|
|
@@ -232,6 +240,13 @@ class Visit:
|
|
|
232
240
|
|
|
233
241
|
@property
|
|
234
242
|
def all_requisitions(self) -> RequisitionCollection:
|
|
243
|
+
"""Return a new collection containing all requisitions.
|
|
244
|
+
|
|
245
|
+
The new collection contains:
|
|
246
|
+
* requisitions
|
|
247
|
+
* requisitions_unscheduled
|
|
248
|
+
* requisitions_prn
|
|
249
|
+
"""
|
|
235
250
|
names = [r.name for r in self.requisitions]
|
|
236
251
|
requisitions = list(self.requisitions) + [
|
|
237
252
|
r for r in self.requisitions_unscheduled if r.name not in names
|
|
@@ -11,6 +11,8 @@ from edc_document_status.model_mixins import DocumentStatusModelMixin
|
|
|
11
11
|
from edc_identifier.model_mixins import NonUniqueSubjectIdentifierFieldMixin
|
|
12
12
|
from edc_metadata.model_mixins import MetadataHelperModelMixin
|
|
13
13
|
from edc_offstudy.model_mixins import OffstudyNonCrfModelMixin
|
|
14
|
+
from edc_timepoint.model_mixins import TimepointLookupModelMixin
|
|
15
|
+
from edc_timepoint.visit_timepoint_lookup import VisitTimepointLookup
|
|
14
16
|
from edc_visit_schedule.model_mixins import VisitScheduleModelMixin
|
|
15
17
|
|
|
16
18
|
from ...constants import MISSED_VISIT, NO_FOLLOW_UP_REASONS
|
|
@@ -29,6 +31,7 @@ class VisitModelMixin(
|
|
|
29
31
|
MetadataHelperModelMixin,
|
|
30
32
|
OffstudyNonCrfModelMixin,
|
|
31
33
|
RequiresConsentFieldsModelMixin,
|
|
34
|
+
TimepointLookupModelMixin,
|
|
32
35
|
models.Model,
|
|
33
36
|
):
|
|
34
37
|
"""
|
|
@@ -41,6 +44,8 @@ class VisitModelMixin(
|
|
|
41
44
|
app_label = 'my_app'
|
|
42
45
|
"""
|
|
43
46
|
|
|
47
|
+
timepoint_lookup_cls = VisitTimepointLookup
|
|
48
|
+
|
|
44
49
|
metadata_helper_instance_attr = None
|
|
45
50
|
|
|
46
51
|
appointment = models.OneToOneField("edc_appointment.appointment", on_delete=PROTECT)
|
|
@@ -8,6 +8,8 @@ from edc_metadata.model_mixins.creates import CreatesMetadataModelMixin
|
|
|
8
8
|
from edc_model.models import BaseUuidModel, HistoricalRecords
|
|
9
9
|
from edc_sites.managers import CurrentSiteManager
|
|
10
10
|
from edc_sites.model_mixins import SiteModelMixin
|
|
11
|
+
from edc_timepoint.model_mixins import TimepointLookupModelMixin
|
|
12
|
+
from edc_timepoint.visit_timepoint_lookup import VisitTimepointLookup
|
|
11
13
|
from edc_visit_tracking.choices import (
|
|
12
14
|
VISIT_INFO_SOURCE,
|
|
13
15
|
VISIT_REASON,
|
|
@@ -22,8 +24,11 @@ class SubjectVisit(
|
|
|
22
24
|
CreatesMetadataModelMixin,
|
|
23
25
|
SiteModelMixin,
|
|
24
26
|
RequiresConsentFieldsModelMixin,
|
|
27
|
+
TimepointLookupModelMixin,
|
|
25
28
|
BaseUuidModel,
|
|
26
29
|
):
|
|
30
|
+
timepoint_lookup_cls = VisitTimepointLookup
|
|
31
|
+
|
|
27
32
|
appointment = models.OneToOneField(
|
|
28
33
|
get_appointment_model_name(),
|
|
29
34
|
on_delete=PROTECT,
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
# from .aliquot_model_wrapper import AliquotModelWrapper
|
|
2
|
-
# from .box_model_wrapper import BoxModelWrapper
|
|
3
|
-
# from .manage_box_item_model_wrapper import ManageBoxItemModelWrapper
|
|
4
|
-
# from .manifest_item_model_wrapper import ManifestItemModelWrapper
|
|
5
|
-
# from .manifest_model_wrapper import ManifestModelWrapper
|
|
6
|
-
# from .requisition_model_wrapper import RequisitionModelWrapper
|
|
7
|
-
# from .result_model_wrapper import ResultModelWrapper
|
|
8
|
-
# from .verify_box_model_wrapper import VerifyBoxItemModelWrapper
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
from edc_model_wrapper import ModelWrapper
|
|
2
|
-
|
|
3
|
-
from edc_lab.models import Aliquot, BoxItem, ManifestItem
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
class AliquotModelWrapper(ModelWrapper):
|
|
7
|
-
model_cls = Aliquot
|
|
8
|
-
next_url_name = "aliquot_listboard_url"
|
|
9
|
-
|
|
10
|
-
@property
|
|
11
|
-
def human_readable_identifier(self):
|
|
12
|
-
return self.object.human_readable_identifier
|
|
13
|
-
|
|
14
|
-
@property
|
|
15
|
-
def box_item(self):
|
|
16
|
-
try:
|
|
17
|
-
return BoxItem.objects.get(identifier=self.aliquot_identifier)
|
|
18
|
-
except BoxItem.DoesNotExist:
|
|
19
|
-
return None
|
|
20
|
-
|
|
21
|
-
@property
|
|
22
|
-
def manifest_item(self):
|
|
23
|
-
manifest_item = None
|
|
24
|
-
if self.box_item:
|
|
25
|
-
try:
|
|
26
|
-
manifest_item = ManifestItem.objects.get(
|
|
27
|
-
identifier=self.box_item.box.box_identifier
|
|
28
|
-
)
|
|
29
|
-
except ManifestItem.DoesNotExist:
|
|
30
|
-
pass
|
|
31
|
-
return manifest_item
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
from django.apps import apps as django_apps
|
|
2
|
-
from edc_model_wrapper import ModelWrapper
|
|
3
|
-
|
|
4
|
-
from edc_lab.models import BoxItem
|
|
5
|
-
|
|
6
|
-
edc_lab_app_config = django_apps.get_app_config("edc_lab")
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
class BaseBoxItemModelWrapper(ModelWrapper):
|
|
10
|
-
model_cls = BoxItem
|
|
11
|
-
action_name = None
|
|
12
|
-
next_url_name = None
|
|
13
|
-
next_url_attrs = ["box_identifier", "action_name"]
|
|
14
|
-
|
|
15
|
-
@property
|
|
16
|
-
def human_readable_identifier(self):
|
|
17
|
-
return self.object.human_readable_identifier
|
|
18
|
-
|
|
19
|
-
@property
|
|
20
|
-
def box_identifier(self):
|
|
21
|
-
return self.object.box.box_identifier
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
from edc_model_wrapper import ModelWrapper
|
|
2
|
-
|
|
3
|
-
from edc_lab.models import Box
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
class BoxModelWrapper(ModelWrapper):
|
|
7
|
-
model_cls = Box
|
|
8
|
-
next_url_name = "pack_listboard_url"
|
|
9
|
-
|
|
10
|
-
@property
|
|
11
|
-
def human_readable_identifier(self):
|
|
12
|
-
return self.object.human_readable_identifier
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
from edc_model_wrapper import ModelWrapper
|
|
2
|
-
|
|
3
|
-
from edc_lab.models import Box, ManifestItem
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
class ManifestItemModelWrapper(ModelWrapper):
|
|
7
|
-
model_cls = ManifestItem
|
|
8
|
-
next_url_name = "manage_manifest_listboard_url"
|
|
9
|
-
action_name = "manage"
|
|
10
|
-
|
|
11
|
-
@property
|
|
12
|
-
def manifest_identifier(self):
|
|
13
|
-
return self.object.manifest.manifest_identifier
|
|
14
|
-
|
|
15
|
-
@property
|
|
16
|
-
def box_identifier(self):
|
|
17
|
-
return self.object.identifier
|
|
18
|
-
|
|
19
|
-
@property
|
|
20
|
-
def box(self):
|
|
21
|
-
return Box.objects.get(box_identifier=self.object.identifier)
|