diff --git a/edc_adverse_event/auth_objects.py b/edc_adverse_event/auth_objects.py index 3917987..2c4a06d 100644 --- a/edc_adverse_event/auth_objects.py +++ b/edc_adverse_event/auth_objects.py @@ -1,14 +1,5 @@ from .utils import get_adverse_event_app_label, get_hospitalization_model_app_label -AE = "AE" -AE_REVIEW = "AE_REVIEW" -AE_ROLE = "ae_role" -AE_SUPER = "AE_SUPER" - -TMG = "TMG" -TMG_REVIEW = "TMG_REVIEW" -TMG_ROLE = "tmg" - ae_codenames = [ "edc_adverse_event.nav_ae_section", "edc_adverse_event.view_ae_listboard", diff --git a/edc_adverse_event/auths.py b/edc_adverse_event/auths.py index 8539d83..039a678 100644 --- a/edc_adverse_event/auths.py +++ b/edc_adverse_event/auths.py @@ -8,13 +8,6 @@ from edc_auth.utils import remove_default_model_permissions_from_edc_permissions from .auth_objects import ( - AE, - AE_REVIEW, - AE_ROLE, - AE_SUPER, - TMG, - TMG_REVIEW, - TMG_ROLE, ae_codenames, ae_dashboard_tuples, ae_navbar_tuples, @@ -22,6 +15,7 @@ tmg_dashboard_tuples, tmg_navbar_tuples, ) +from .constants import AE, AE_REVIEW, AE_ROLE, AE_SUPER, TMG, TMG_REVIEW, TMG_ROLE site_auths.add_post_update_func( "edc_adverse_event", remove_default_model_permissions_from_edc_permissions diff --git a/edc_adverse_event/constants.py b/edc_adverse_event/constants.py index 07b04f7..49d7523 100644 --- a/edc_adverse_event/constants.py +++ b/edc_adverse_event/constants.py @@ -28,3 +28,12 @@ RECOVERING = "recovering" STUDY_TERMINATION_CONCLUSION_ACTION = "submit-study-termination-conclusion" UNLIKELY_RELATED = "unlikely_related" + +# roles +AE = "AE" +AE_REVIEW = "AE_REVIEW" +AE_ROLE = "ae_role" +AE_SUPER = "AE_SUPER" +TMG = "TMG" +TMG_REVIEW = "TMG_REVIEW" +TMG_ROLE = "tmg" diff --git a/edc_adverse_event/modelform_mixins/ae_tmg_modelform_mixin.py b/edc_adverse_event/modelform_mixins/ae_tmg_modelform_mixin.py index 8b5ce6a..2934de7 100644 --- a/edc_adverse_event/modelform_mixins/ae_tmg_modelform_mixin.py +++ b/edc_adverse_event/modelform_mixins/ae_tmg_modelform_mixin.py @@ -1,7 +1,7 @@ from django import forms from ..form_validators import AeTmgFormValidator -from .ae_modelform_mixin import AeModelFormMixin +from . import AeModelFormMixin class AeTmgModelFormMixin(AeModelFormMixin): diff --git a/edc_adverse_event/signals.py b/edc_adverse_event/signals.py index 724b1e3..ec67dcf 100644 --- a/edc_adverse_event/signals.py +++ b/edc_adverse_event/signals.py @@ -6,8 +6,7 @@ from edc_notification.models import Notification from edc_utils import get_utcnow -from .auth_objects import TMG -from .constants import AE_TMG_ACTION, DEATH_REPORT_TMG_ACTION +from .constants import AE_TMG_ACTION, DEATH_REPORT_TMG_ACTION, TMG from .utils import get_ae_model AeInitial = get_ae_model("AeInitial") diff --git a/edc_adverse_event/templates/edc_adverse_event/bootstrap3/tmg/ae_tmg_panel.html b/edc_adverse_event/templates/edc_adverse_event/bootstrap3/tmg/ae_tmg_panel.html index 4d8ccd9..6921c0f 100644 --- a/edc_adverse_event/templates/edc_adverse_event/bootstrap3/tmg/ae_tmg_panel.html +++ b/edc_adverse_event/templates/edc_adverse_event/bootstrap3/tmg/ae_tmg_panel.html @@ -1,15 +1,15 @@ {% load i18n %} -
- - {{ label }} - -  {{ action_item.display_name|cut:"Submit"|cut:"pending" }} {{ action_item.identifier|default:"New" }} -  {% if report_status == OPEN %}OPEN{% endif %} + + {{ btn.label }} +   + {{ panel_label }} {% if report_status == OPEN %}OPEN{% endif %}
{% if reference_obj %}
{% trans "Created" %}: {{ reference_obj.user_created|default:"---" }} {{ reference_obj.created|date:"SHORT_DATETIME_FORMAT"|default:"---" }}
{% trans "Last modified" %}: {{ reference_obj.user_modified|default:"---" }} {{ reference_obj.modified|date:"SHORT_DATETIME_FORMAT"|default:"---" }}
+ {% if reference_obj.report_status == CLOSED %} +
{% trans "Report closed" %}: {{ reference_obj.report_closed_datetime|date:"SHORT_DATETIME_FORMAT"|default:"---" }}
+ {% endif %} {% endif %} +
Action first created: {{ action_item.report_datetime|date:"SHORT_DATETIME_FORMAT" }}
diff --git a/edc_adverse_event/templates/edc_adverse_event/bootstrap3/tmg/tmg_ae_listboard.html b/edc_adverse_event/templates/edc_adverse_event/bootstrap3/tmg/tmg_ae_listboard.html index 53313d8..61374b9 100644 --- a/edc_adverse_event/templates/edc_adverse_event/bootstrap3/tmg/tmg_ae_listboard.html +++ b/edc_adverse_event/templates/edc_adverse_event/bootstrap3/tmg/tmg_ae_listboard.html @@ -23,15 +23,19 @@ - +x {# results in qs of ActionItem #} + {% if status == NEW %} - {% tmg_listboard_results results "There are no new reports to submit for this site." %} + {% get_empty_qs_message "new" search_term as msg %} + {% tmg_listboard_results results msg %} {% elif status == OPEN %} - {% tmg_listboard_results results "There are no open reports to submit for this site." %} + {% get_empty_qs_message "open" search_term as msg %} + {% tmg_listboard_results results msg %} {% elif status == CLOSED %} - {% tmg_listboard_results results "There are no closed reports for this site." %} + {% get_empty_qs_message "closed" search_term as msg %} + {% tmg_listboard_results results msg %} {% endif %} diff --git a/edc_adverse_event/templates/edc_adverse_event/bootstrap3/tmg/tmg_ae_listboard_result.html b/edc_adverse_event/templates/edc_adverse_event/bootstrap3/tmg/tmg_ae_listboard_result.html index 6dc01ec..a6b6328 100644 --- a/edc_adverse_event/templates/edc_adverse_event/bootstrap3/tmg/tmg_ae_listboard_result.html +++ b/edc_adverse_event/templates/edc_adverse_event/bootstrap3/tmg/tmg_ae_listboard_result.html @@ -3,76 +3,81 @@ {% load static %} {% load edc_adverse_event_extras %} -
-
- {% if not results %} -
{{ empty_message }}
- {% endif %} - {% has_perms_for_tmg_role as may_access_page %} - {% if may_access_page %} - {% for result in results %} -
-
{{ forloop.counter }} {{ result.subject_identifier }} {% copy_string_to_clipboard_button result.subject_identifier %} {{ utc_date|timeuntil:result.report_datetime.date }} ago
-
-
-
+{% has_perms_for_tmg_role as may_access_page %} +{% if may_access_page %} +
+
+ {% if not results %} +
{{ empty_message }}
+ {% endif %} + {% has_perms_for_tmg_role as may_access_page %} + {% if may_access_page %} + {% for result in results %} +
+
{{ forloop.counter }} {{ result.subject_identifier }} {% copy_string_to_clipboard_button result.subject_identifier %} {{ utc_date|timeuntil:result.report_datetime.date }} ago
+
+
+
-
- {% render_tmg_panel action_item=result change=True by_user_created_only=True counter=forloop.counter report_status=result.report_status %} -
+
+ {# AE TMG #} + {% render_tmg_panel action_item=result by_user_created_only=True counter=forloop.counter report_status=result.reference_obj.report_status %} +
- {% death_report_tmg_queryset action_item=result as qs %} - {% for death_report_tmg in qs %} - {% render_tmg_panel reference_obj=death_report_tmg change=True by_user_created_only=True counter=forloop.counter %} - {% endfor %} + {% death_report_tmg_queryset action_item=result as qs %} + {% for death_report_tmg in qs %} + {% render_tmg_panel reference_obj=death_report_tmg by_user_created_only=True counter=forloop.counter %} + {% endfor %} - {% death_report_tmg2_queryset action_item=result as qs %} - {% for death_report_tmg2 in qs %} - {% render_tmg_panel reference_obj=death_report_tmg2 change=True by_user_created_only=True counter=forloop.counter %} - {% endfor %} + {% death_report_tmg2_queryset action_item=result as qs %} + {% for death_report_tmg2 in qs %} + {% render_tmg_panel reference_obj=death_report_tmg2 by_user_created_only=True counter=forloop.counter %} + {% endfor %} -
+
-
-
- {% render_tmg_panel action_item=result.parent_action_item view_only=True counter=forloop.counter %} - {% if result.parent_action_item.reference_obj.action_identifier != result.related_action_item.reference_obj.action_identifier %} - {% render_tmg_panel action_item=result.related_action_item view_only=True counter=forloop.counter %} - {% endif %} +
+
+ {# AE INTIAL #} + {% render_tmg_panel action_item=result.parent_action_item counter=forloop.counter %} + {% if result.parent_action_item.reference_obj.action_identifier != result.related_action_item.reference_obj.action_identifier %} + {% render_tmg_panel action_item=result.related_action_item counter=forloop.counter %} + {% endif %} +
-
-
+
- {% ae_followup_queryset ae_initial=result.parent_action_item.reference_obj as qs %} - {% if qs.count == 0 %}
There are no follow-ups to this AE
{% endif %} - {% for ae_followup in qs %} - {% render_tmg_panel reference_obj=ae_followup view_only=True counter=forloop.counter %} - {% endfor %} + {% ae_followup_queryset ae_initial=result.parent_action_item.reference_obj as qs %} + {% if qs.count == 0 %}
There are no follow-ups to this AE
{% endif %} + {% for ae_followup in qs %} + {% render_tmg_panel reference_obj=ae_followup counter=forloop.counter %} + {% endfor %} - {% death_report_queryset subject_identifier=result.subject_identifier as qs %} - {% for death_report in qs %} - {% render_tmg_panel reference_obj=death_report view_only=True counter=forloop.counter %} - {% endfor %} + {% death_report_queryset subject_identifier=result.subject_identifier as qs %} + {% for death_report in qs %} + {% render_tmg_panel reference_obj=death_report counter=forloop.counter %} + {% endfor %} - + -
- {{ result.identifier }} {{ result.display_name }} -
+
+ {{ result.identifier }} {{ result.display_name }} +
+
+
-
+ {% endfor %} + {% else %} +
+ You do not have permissions to view this page. Only users with the TMG Role are allowed access. Check with your administrator.
- {% endfor %} - {% else %} -
- You do not have permissions to view this page. Only users with the TMG Role are allowed access. Check with your administrator. -
- {% endif %} -
{% paginator_row %}
+ {% endif %} +
{% paginator_row %}
+
-
+{% endif %} diff --git a/edc_adverse_event/templatetags/edc_adverse_event_extras.py b/edc_adverse_event/templatetags/edc_adverse_event_extras.py index 62c8d66..3e4e7a0 100644 --- a/edc_adverse_event/templatetags/edc_adverse_event_extras.py +++ b/edc_adverse_event/templatetags/edc_adverse_event_extras.py @@ -6,19 +6,20 @@ from django import template from django.conf import settings -from django.contrib.auth import get_permission_codename +from django.contrib.messages import ERROR from django.core.exceptions import ObjectDoesNotExist from django.template.loader import select_template from django.utils.html import format_html +from django.utils.translation import gettext as _ from edc_action_item.utils import get_reference_obj -from edc_constants.constants import OPEN, OTHER, YES +from edc_constants.constants import CLOSED, OPEN, OTHER, YES from edc_dashboard.utils import get_bootstrap_version +from edc_model_admin.utils import add_to_messages_once from edc_utils import get_utcnow -from .. import get_ae_model -from ..auth_objects import TMG_ROLE -from ..constants import AE_WITHDRAWN -from ..utils import get_adverse_event_app_label +from ..constants import AE_WITHDRAWN, TMG_ROLE +from ..utils import get_adverse_event_app_label, get_ae_model, has_valid_tmg_perms +from ..view_utils import TmgButton if TYPE_CHECKING: from django.db.models import QuerySet @@ -28,19 +29,23 @@ from ..model_mixins import ( AeFollowupModelMixin, AeInitialModelMixin, + DeathReportModelMixin, DeathReportTmgModelMixin, ) - class DeathReportTmg(DeathReportTmgModelMixin, BaseUuidModel): + class DeathReportTmgModel(DeathReportTmgModelMixin, BaseUuidModel): ... - class DeathReportTmgSecond(DeathReportTmgModelMixin, BaseUuidModel): + class DeathReportTmgSecondModel(DeathReportTmgModelMixin, BaseUuidModel): ... - class AeInitial(AeInitialModelMixin, BaseUuidModel): + class AeInitialModel(AeInitialModelMixin, BaseUuidModel): ... - class AeFollowup(AeFollowupModelMixin, BaseUuidModel): + class AeFollowupModel(AeFollowupModelMixin, BaseUuidModel): + ... + + class DeathReportModel(DeathReportModelMixin, BaseUuidModel): ... @@ -70,19 +75,6 @@ def select_description_template(model): return select_ae_template(f"{model}_description.html").template.name -@register.inclusion_tag( - f"edc_adverse_event/bootstrap{get_bootstrap_version()}/" - f"tmg/tmg_ae_listboard_result.html", - takes_context=True, -) -def tmg_listboard_results( - context, results: [ActionItem], empty_message: str | None = None -) -> dict: - context["results"] = results - context["empty_message"] = empty_message - return context - - @register.inclusion_tag(select_description_template("aeinitial"), takes_context=True) def format_ae_description(context, ae_initial, wrap_length): context["utc_date"] = get_utcnow().date() @@ -137,6 +129,19 @@ def format_ae_susar_description(context, ae_susar, wrap_length): return context +@register.inclusion_tag( + f"edc_adverse_event/bootstrap{get_bootstrap_version()}/" + f"tmg/tmg_ae_listboard_result.html", + takes_context=True, +) +def tmg_listboard_results( + context, results: [ActionItem], empty_qs_message: str | None = None +) -> dict: + context["results"] = results + context["empty_message"] = empty_qs_message + return context + + @register.inclusion_tag( f"edc_adverse_event/bootstrap{get_bootstrap_version()}/tmg/death_report_tmg_panel.html", takes_context=True, @@ -146,7 +151,7 @@ def render_death_report_tmg_panel(context, action_item: ActionItem = None): @register.simple_tag -def death_report_tmg_queryset(action_item: ActionItem = None) -> QuerySet[DeathReportTmg]: +def death_report_tmg_queryset(action_item: ActionItem = None) -> QuerySet[DeathReportTmgModel]: return get_ae_model("deathreporttmg").objects.filter( subject_identifier=action_item.subject_identifier ) @@ -155,7 +160,7 @@ def death_report_tmg_queryset(action_item: ActionItem = None) -> QuerySet[DeathR @register.simple_tag def death_report_tmg2_queryset( action_item: ActionItem = None, -) -> QuerySet[DeathReportTmgSecond]: +) -> QuerySet[DeathReportTmgSecondModel]: return get_ae_model("deathreporttmgsecond").objects.filter( subject_identifier=action_item.subject_identifier ) @@ -164,12 +169,14 @@ def death_report_tmg2_queryset( @register.simple_tag def death_report_queryset( subject_identifier: str = None, -) -> QuerySet[DeathReportTmgSecond]: +) -> QuerySet[DeathReportTmgSecondModel]: return get_ae_model("deathreport").objects.filter(subject_identifier=subject_identifier) @register.simple_tag -def ae_followup_queryset(ae_initial: AeInitial = None) -> QuerySet[AeFollowup] | None: +def ae_followup_queryset( + ae_initial: AeInitialModel = None, +) -> QuerySet[AeFollowupModel] | None: if ae_initial: return get_ae_model("aefollowup").objects.filter(ae_initial_id=ae_initial.id) return None @@ -182,115 +189,71 @@ def ae_followup_queryset(ae_initial: AeInitial = None) -> QuerySet[AeFollowup] | def render_tmg_panel( context, action_item: ActionItem = None, - reference_obj: DeathReportTmg = None, - change: bool | None = None, + reference_obj: DeathReportTmgModel = None, view_only: bool | None = None, by_user_created_only: bool | None = None, counter: int = None, report_status: str | None = None, ) -> dict: - # must have either action item or reference_obj reference_obj = reference_obj or get_reference_obj(action_item) if not action_item and reference_obj: action_item = reference_obj.action_item - may_access_tmg_obj = has_perms_for_obj( - context, - reference_obj=reference_obj, - change=change, - view_only=view_only, - by_user_created_only=by_user_created_only, + disable_all = True if not has_valid_tmg_perms(request=context["request"]) else False + btn = TmgButton( + user=context["request"].user, + model_obj=reference_obj, + model_cls=action_item.action_cls.reference_model_cls(), + request=context["request"], + only_user_created_may_access=by_user_created_only, + forloop_counter=counter, + current_site=context["request"].site, + disable_all=disable_all, ) - disabled = "disabled" if not may_access_tmg_obj else "" - if view_only: - label = "View" - fa_icon = "fa-eye" + panel_color = "info" elif not reference_obj: - label = "Add" - fa_icon = "fa-plus" + panel_color = "warning" else: - label = "Edit" if reference_obj else "view" - fa_icon = "fa-pencil" if reference_obj else "fa-plus" + panel_color = "success" + + # panel_label + display_name = action_item.display_name.replace("Submit", "").replace("pending", "") + identifier = action_item.identifier or "New" + panel_label = _(f"{display_name} {identifier}") - if view_only: - panel_color = "info" - else: - panel_color = "success" if reference_obj else "warning" return dict( + btn=btn, + panel_color=panel_color, reference_obj=reference_obj, action_item=action_item, - may_access_tmg_obj=may_access_tmg_obj, - counter=counter, - panel_color=panel_color, - disabled=disabled, - label=label, - fa_icon=fa_icon, - view_only=view_only, - report_status=report_status, OPEN=OPEN, - ) - - -@register.inclusion_tag( - f"edc_adverse_event/bootstrap{get_bootstrap_version()}/tmg/ae_tmg_panel.html", - takes_context=True, -) -def render_ae_initial_panel( - context, - action_item: ActionItem = None, - counter: int = None, -) -> dict: - may_access_tmg_obj = has_perms_for_obj( - context, - action_item=action_item, - view_only=True, - ) - return dict( - action_item=action_item, - may_access_tmg_obj=may_access_tmg_obj, - counter=counter, - panel_color="info", + CLOSED=CLOSED, + report_status=report_status, + panel_label=panel_label, ) -@register.simple_tag(takes_context=True) -def has_perms_for_obj( - context, - action_item: ActionItem | None = None, - reference_obj: DeathReportTmg = None, - change: bool | None = None, - view_only: bool | None = None, - by_user_created_only: bool | None = None, -) -> bool: - has_perms = False - - reference_obj = reference_obj or get_reference_obj(action_item) - - if reference_obj: - app_label = reference_obj._meta.app_label - add_codename = get_permission_codename("add", reference_obj._meta) - change_codename = get_permission_codename("change", reference_obj._meta) - view_codename = get_permission_codename("view", reference_obj._meta) - has_change_perms = context["request"].user.has_perms( - [f"{app_label}.{add_codename}", f"{app_label}.{change_codename}"] - ) - has_view_perms = context["request"].user.has_perm(f"{app_label}.{view_codename}") - if change: - has_perms = has_change_perms - elif view_only: - has_perms = not has_change_perms and has_view_perms - if by_user_created_only: - has_perms = ( - has_perms and reference_obj.user_created == context["request"].user.username - ) - return has_perms - - @register.simple_tag(takes_context=True) def has_perms_for_tmg_role(context): has_perms = False try: has_perms = context["request"].user.userprofile.roles.get(name=TMG_ROLE) except ObjectDoesNotExist: - pass + add_to_messages_once( + context["request"], + ERROR, + _( + "Access disabled. User has not been granted a TMG role. " + "Contact your administrator." + ), + ) + return has_perms + + +@register.simple_tag() +def get_empty_qs_message(status: str, search_term: str): + msg = f"There are no {status} reports." + if search_term: + msg = f"{msg[:-1]} for your search criteria" + return _(msg) diff --git a/edc_adverse_event/utils.py b/edc_adverse_event/utils.py index c4e75fc..59c0177 100644 --- a/edc_adverse_event/utils.py +++ b/edc_adverse_event/utils.py @@ -5,9 +5,18 @@ from django import forms from django.apps import apps as django_apps from django.conf import settings +from django.contrib.auth import get_permission_codename +from django.contrib.messages import ERROR +from django.core.exceptions import ObjectDoesNotExist +from django.utils.translation import gettext as _ +from edc_model_admin.utils import add_to_messages_once from edc_utils import convert_php_dateformat +from .constants import TMG_ROLE + if TYPE_CHECKING: + from django.core.handlers.wsgi import WSGIRequest + from edc_adverse_event.model_mixins import ( AeFollowupModelMixin, AeInitialModelMixin, @@ -62,3 +71,51 @@ def get_ae_model( def get_ae_model_name(model_name: str) -> str: return f"{get_adverse_event_app_label()}.{model_name}" + + +def has_valid_tmg_perms(request: WSGIRequest, add_message: bool = None): + """Checks if user has TMG_ROLE but not granted add/change + perms to any non-TMG AE models. + + add_message: if True, adds a message to message context. + """ + non_tmg_ae_models = ["aeinitial", "aefollowup", "deathreport"] + # check role + try: + has_valid_perms = request.user.userprofile.roles.get(name=TMG_ROLE) + except ObjectDoesNotExist: + has_valid_perms = False + if add_message: + add_to_messages_once( + request, + ERROR, + ( + "Access disabled. User has not been granted a TMG role. " + "Contact your administrator." + ), + ) + # check AE model perms + if has_valid_tmg_perms: + codenames = {} + for model_name in non_tmg_ae_models: + model_cls = get_ae_model(model_name) + codename = get_permission_codename("change", model_cls._meta) + codenames.update({model_cls: f"{model_cls._meta.app_label}.{codename}"}) + for model_cls, codename in codenames.items(): + if request.user.has_perm(codename): + if add_message: + add_to_messages_once( + request, + ERROR, + ( + _( + "Access disabled. A TMG user may not have change " + "permission for any adverse event form. Contact your " + "administrator. Got %(verbose_name)s" + ) + % {"verbose_name": model_cls._meta.verbose_name} + ), + ) + has_valid_perms = False + break + return has_valid_perms diff --git a/edc_adverse_event/view_mixins/tmg/tmg_ae_listboard_view_mixin.py b/edc_adverse_event/view_mixins/tmg/tmg_ae_listboard_view_mixin.py index d44451d..404c652 100644 --- a/edc_adverse_event/view_mixins/tmg/tmg_ae_listboard_view_mixin.py +++ b/edc_adverse_event/view_mixins/tmg/tmg_ae_listboard_view_mixin.py @@ -11,7 +11,7 @@ from edc_utils import get_utcnow from ...constants import AE_TMG_ACTION -from ...utils import get_adverse_event_app_label +from ...utils import get_adverse_event_app_label, has_valid_tmg_perms if TYPE_CHECKING: from django.db.models import Q @@ -73,6 +73,7 @@ class StatusTmgAeListboardView(TmgAeListboardViewMixin): status = None def get_context_data(self, **kwargs) -> dict[str, Any]: + has_valid_tmg_perms(self.request, add_message=True) kwargs.update(status=self.status) return super().get_context_data(**kwargs) diff --git a/edc_adverse_event/view_utils/__init__.py b/edc_adverse_event/view_utils/__init__.py new file mode 100644 index 0000000..e0fea1a --- /dev/null +++ b/edc_adverse_event/view_utils/__init__.py @@ -0,0 +1 @@ +from .tmg_button import TmgButton diff --git a/edc_adverse_event/view_utils/tmg_button.py b/edc_adverse_event/view_utils/tmg_button.py new file mode 100644 index 0000000..33eaa93 --- /dev/null +++ b/edc_adverse_event/view_utils/tmg_button.py @@ -0,0 +1,93 @@ +from __future__ import annotations + +from dataclasses import dataclass, field +from typing import TYPE_CHECKING + +from django.utils.translation import gettext as _ +from edc_subject_dashboard.view_utils import ModelButton + +if TYPE_CHECKING: + from edc_model.models import BaseUuidModel + + from edc_adverse_event.model_mixins import ( + AeFollowupModelMixin, + AeInitialModelMixin, + DeathReportModelMixin, + DeathReportTmgModelMixin, + ) + + class AeInitialModel(AeInitialModelMixin, BaseUuidModel): + ... + + class AeFollowupModel(AeFollowupModelMixin, BaseUuidModel): + ... + + class DeathReportTmgModel(DeathReportTmgModelMixin, BaseUuidModel): + ... + + class DeathReportModel(DeathReportModelMixin, BaseUuidModel): + ... + + +@dataclass +class TmgButton(ModelButton): + model_obj: DeathReportTmgModel | DeathReportModel | AeFollowupModel | AeInitialModel = None + next_url_name: str = "open_tmg_ae_listboard_url" + only_user_created_may_access: bool | None = None + forloop_counter: int | None = None + colors: tuple[str, str, str] = field(default=("warning", "success", "success")) + titles: tuple[str, str, str] = field(default=(_("Add"), _("Change"), _("View"))) + + disable_all: bool = False + + @property + def disabled(self) -> str: + if self.disable_all: + disabled = "disabled" + else: + disabled = super().disabled + if ( + self.only_user_created_may_access + and self.model_obj.user_created != self.user.username + ): + disabled = "disabled" + return disabled + + @property + def fa_icon(self) -> str: + if self.disabled: + return "fa-eye-slash" + return super().fa_icon + + @property + def btn_id(self) -> str: + if self.forloop_counter is not None: + return str(self.forloop_counter) + return super().btn_id + + @property + def title(self) -> str: + if ( + self.model_obj + and self.only_user_created_may_access + and self.model_obj.user_created != self.user.username + ): + title = _("May only be edited by %(user)s") % {"user": self.model_obj.user_created} + if self.model_obj.site.id != self.request.site.id: + title = _("%(title)s when logged into site %(site)s") % { + "title": title, + "site": self.model_obj.site.id, + } + else: + title = super().title + return title + + @property + def label(self) -> str: + if ( + self.model_obj + and self.only_user_created_may_access + and self.model_obj.user_created != self.user.username + ): + return _("View") + return _(super().label)