From 39369ce2450a7906a20ca75f7910f46467e25e4b Mon Sep 17 00:00:00 2001 From: sandeepsajan0 Date: Mon, 25 Nov 2024 17:59:15 +0530 Subject: [PATCH 1/8] Remove old submissions table, removed old table batch actions, update invoice batch action to use htmx --- eslint.config.mjs | 1 + .../batch_determination_form.html | 6 +- .../batch_determination_confirmation.html | 12 - hypha/apply/funds/forms.py | 82 ---- .../funds/base_submissions_table.html | 2 +- .../batch_archive_submission_form.html | 16 - .../batch_delete_submission_form.html | 16 - .../funds/includes/batch_progress_form.html | 11 - .../includes/batch_update_lead_form.html | 13 - .../includes/batch_update_reviewer_form.html | 13 - .../includes/table_filter_and_search.html | 60 +-- .../templates/funds/reviewer_leaderboard.html | 2 +- hypha/apply/funds/templates/funds/rounds.html | 2 +- .../funds/templates/funds/submissions.html | 45 --- .../templates/funds/submissions_by_round.html | 18 - .../funds/submissions_by_status.html | 21 - .../templates/funds/submissions_result.html | 2 +- .../funds/templates/submissions/all.html | 3 +- hypha/apply/funds/urls.py | 4 - hypha/apply/funds/views.py | 360 ------------------ hypha/apply/projects/forms/payment.py | 4 +- .../includes/batch_invoice_status_update.html | 13 - .../application_projects/invoice_list.html | 2 +- .../modals/batch_invoice_status_update.html | 28 ++ .../application_projects/project_list.html | 2 +- hypha/apply/projects/urls.py | 6 + hypha/apply/projects/views/__init__.py | 2 + hypha/apply/projects/views/payment.py | 64 ++-- hypha/static_src/javascript/batch-actions.js | 116 ++---- .../sass/components/_list-reveal.scss | 3 +- 30 files changed, 123 insertions(+), 806 deletions(-) delete mode 100644 hypha/apply/determinations/templates/determinations/includes/batch_determination_confirmation.html delete mode 100644 hypha/apply/funds/templates/funds/includes/batch_archive_submission_form.html delete mode 100644 hypha/apply/funds/templates/funds/includes/batch_delete_submission_form.html delete mode 100644 hypha/apply/funds/templates/funds/includes/batch_progress_form.html delete mode 100644 hypha/apply/funds/templates/funds/includes/batch_update_lead_form.html delete mode 100644 hypha/apply/funds/templates/funds/includes/batch_update_reviewer_form.html delete mode 100644 hypha/apply/funds/templates/funds/submissions.html delete mode 100644 hypha/apply/funds/templates/funds/submissions_by_round.html delete mode 100644 hypha/apply/funds/templates/funds/submissions_by_status.html delete mode 100644 hypha/apply/projects/templates/application_projects/includes/batch_invoice_status_update.html create mode 100644 hypha/apply/projects/templates/application_projects/modals/batch_invoice_status_update.html diff --git a/eslint.config.mjs b/eslint.config.mjs index c91087dccb..2a8e04858b 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -26,6 +26,7 @@ export default [ ...globals.commonjs, jQuery: true, Alpine: true, + htmx: true, }, }, diff --git a/hypha/apply/determinations/templates/determinations/batch_determination_form.html b/hypha/apply/determinations/templates/determinations/batch_determination_form.html index d2903360f4..b058c36b93 100644 --- a/hypha/apply/determinations/templates/determinations/batch_determination_form.html +++ b/hypha/apply/determinations/templates/determinations/batch_determination_form.html @@ -30,9 +30,9 @@ {% endblock %} {% block form_buttons %} - - {% include "determinations/includes/batch_determination_confirmation.html" with count=submissions.count %} - + {% endblock %} {% block show_submission %} diff --git a/hypha/apply/determinations/templates/determinations/includes/batch_determination_confirmation.html b/hypha/apply/determinations/templates/determinations/includes/batch_determination_confirmation.html deleted file mode 100644 index e1d1b4e493..0000000000 --- a/hypha/apply/determinations/templates/determinations/includes/batch_determination_confirmation.html +++ /dev/null @@ -1,12 +0,0 @@ -{% load i18n %} - diff --git a/hypha/apply/funds/forms.py b/hypha/apply/funds/forms.py index 5ddeeb000e..5712b8a123 100644 --- a/hypha/apply/funds/forms.py +++ b/hypha/apply/funds/forms.py @@ -22,7 +22,6 @@ from .permissions import can_change_external_reviewers from .utils import model_form_initial, render_icon from .widgets import MetaTermSelect2Widget, Select2MultiCheckboxesWidget -from .workflow import get_action_mapping class ApplicationSubmissionModelForm(forms.ModelForm): @@ -76,34 +75,6 @@ def __init__(self, *args, **kwargs): action_field.choices = choices -class BatchProgressSubmissionForm(forms.Form): - action = forms.ChoiceField(label=_("Take action")) - submissions = forms.CharField( - widget=forms.HiddenInput(attrs={"class": "js-submissions-id"}) - ) - - def __init__(self, *args, round=None, **kwargs): - self.user = kwargs.pop("user") - super().__init__(*args, **kwargs) - workflow = round and round.workflow - self.action_mapping = get_action_mapping(workflow) - choices = [ - (action, detail["display"]) - for action, detail in self.action_mapping.items() - ] - self.fields["action"].choices = choices - - def clean_submissions(self): - value = self.cleaned_data["submissions"] - submission_ids = [int(submission) for submission in value.split(",")] - return ApplicationSubmission.objects.filter(id__in=submission_ids) - - def clean_action(self): - value = self.cleaned_data["action"] - action = self.action_mapping[value]["transitions"] - return action - - class UpdateSubmissionLeadForm(ApplicationSubmissionModelForm): class Meta: model = ApplicationSubmission @@ -116,59 +87,6 @@ def __init__(self, *args, **kwargs): lead_field.queryset = lead_field.queryset.exclude(id=self.instance.lead.id) -class BatchUpdateSubmissionLeadForm(forms.Form): - lead = forms.ChoiceField(label=_("Lead")) - submissions = forms.CharField( - widget=forms.HiddenInput(attrs={"class": "js-submissions-id"}) - ) - - def __init__(self, *args, round=None, **kwargs): - self.user = kwargs.pop("user") - super().__init__(*args, **kwargs) - self.fields["lead"].choices = [ - (staff.id, staff) for staff in User.objects.staff() - ] - - def clean_lead(self): - value = self.cleaned_data["lead"] - return User.objects.get(id=value) - - def clean_submissions(self): - value = self.cleaned_data["submissions"] - submission_ids = [int(submission) for submission in value.split(",")] - return ApplicationSubmission.objects.filter(id__in=submission_ids) - - -class BatchDeleteSubmissionForm(forms.Form): - submissions = forms.CharField( - widget=forms.HiddenInput(attrs={"class": "js-submissions-id"}) - ) - - def __init__(self, *args, round=None, **kwargs): - self.user = kwargs.pop("user") - super().__init__(*args, **kwargs) - - def clean_submissions(self): - value = self.cleaned_data["submissions"] - submission_ids = [int(submission) for submission in value.split(",")] - return ApplicationSubmission.objects.filter(id__in=submission_ids) - - -class BatchArchiveSubmissionForm(forms.Form): - submissions = forms.CharField( - widget=forms.HiddenInput(attrs={"class": "js-submissions-id"}) - ) - - def __init__(self, *args, round=None, **kwargs): - self.user = kwargs.pop("user") - super().__init__(*args, **kwargs) - - def clean_submissions(self): - value = self.cleaned_data["submissions"] - submission_ids = [int(submission) for submission in value.split(",")] - return ApplicationSubmission.objects.filter(id__in=submission_ids) - - class UpdateReviewersForm(ApplicationSubmissionModelForm): reviewer_reviewers = forms.ModelMultipleChoiceField( queryset=User.objects.reviewers().only("pk", "full_name"), diff --git a/hypha/apply/funds/templates/funds/base_submissions_table.html b/hypha/apply/funds/templates/funds/base_submissions_table.html index fddfd0f064..17d7ef904d 100644 --- a/hypha/apply/funds/templates/funds/base_submissions_table.html +++ b/hypha/apply/funds/templates/funds/base_submissions_table.html @@ -9,7 +9,7 @@ {% block content %} {% block table %} - {% include "funds/includes/table_filter_and_search.html" with filter_form=filter_form search_term=search_term use_search=True filter_action=filter_action use_batch_actions=True filter_classes="filters-open" can_export=can_export %} + {% include "funds/includes/table_filter_and_search.html" with filter_form=filter_form search_term=search_term use_search=True filter_action=filter_action filter_classes="filters-open" can_export=can_export %} {% render_table table %} {% endblock %} diff --git a/hypha/apply/funds/templates/funds/includes/batch_archive_submission_form.html b/hypha/apply/funds/templates/funds/includes/batch_archive_submission_form.html deleted file mode 100644 index e7b41dd823..0000000000 --- a/hypha/apply/funds/templates/funds/includes/batch_archive_submission_form.html +++ /dev/null @@ -1,16 +0,0 @@ -{% load i18n %} - diff --git a/hypha/apply/funds/templates/funds/includes/batch_delete_submission_form.html b/hypha/apply/funds/templates/funds/includes/batch_delete_submission_form.html deleted file mode 100644 index 10cb903c15..0000000000 --- a/hypha/apply/funds/templates/funds/includes/batch_delete_submission_form.html +++ /dev/null @@ -1,16 +0,0 @@ -{% load i18n %} - diff --git a/hypha/apply/funds/templates/funds/includes/batch_progress_form.html b/hypha/apply/funds/templates/funds/includes/batch_progress_form.html deleted file mode 100644 index 668b998470..0000000000 --- a/hypha/apply/funds/templates/funds/includes/batch_progress_form.html +++ /dev/null @@ -1,11 +0,0 @@ -{% load i18n %} - diff --git a/hypha/apply/funds/templates/funds/includes/batch_update_lead_form.html b/hypha/apply/funds/templates/funds/includes/batch_update_lead_form.html deleted file mode 100644 index 6d35fe51b3..0000000000 --- a/hypha/apply/funds/templates/funds/includes/batch_update_lead_form.html +++ /dev/null @@ -1,13 +0,0 @@ -{% load i18n %} - diff --git a/hypha/apply/funds/templates/funds/includes/batch_update_reviewer_form.html b/hypha/apply/funds/templates/funds/includes/batch_update_reviewer_form.html deleted file mode 100644 index dfa2c2d0d3..0000000000 --- a/hypha/apply/funds/templates/funds/includes/batch_update_reviewer_form.html +++ /dev/null @@ -1,13 +0,0 @@ -{% load i18n %} - diff --git a/hypha/apply/funds/templates/funds/includes/table_filter_and_search.html b/hypha/apply/funds/templates/funds/includes/table_filter_and_search.html index d2270e7159..a430744f99 100644 --- a/hypha/apply/funds/templates/funds/includes/table_filter_and_search.html +++ b/hypha/apply/funds/templates/funds/includes/table_filter_and_search.html @@ -9,51 +9,16 @@

{{ heading }}

{% endif %} - - {% if use_batch_actions %} + {% if invoice_batch_actions %}

0 {% trans "Selected" %}

- - {% if not project_actions %} - - - - - - - - - {% if can_bulk_archive %} - - {% endif %} - {% elif invoice_actions %} - - {% endif %} +
{% endif %} + {# Right #} @@ -140,16 +105,3 @@

{{ heading }}

- -{% if use_batch_actions %} - {% include "funds/includes/batch_update_lead_form.html" %} - {% include "funds/includes/batch_update_reviewer_form.html" %} - {% include "funds/includes/batch_progress_form.html" %} - {% include "funds/includes/batch_delete_submission_form.html" %} - {% include "funds/includes/batch_archive_submission_form.html" %} - {% if project_actions %} - {% if invoice_actions %} - {% include "application_projects/includes/batch_invoice_status_update.html" %} - {% endif %} - {% endif %} -{% endif %} diff --git a/hypha/apply/funds/templates/funds/reviewer_leaderboard.html b/hypha/apply/funds/templates/funds/reviewer_leaderboard.html index 7779ab602d..e07cb0e32e 100644 --- a/hypha/apply/funds/templates/funds/reviewer_leaderboard.html +++ b/hypha/apply/funds/templates/funds/reviewer_leaderboard.html @@ -14,7 +14,7 @@
{% block table %} {% trans "All reviewers" as all_reviewers %} - {% include "funds/includes/table_filter_and_search.html" with filter_form=filter_form search_term=search_term search_placeholder="reviewers" use_search=True filter_action=filter_action use_batch_actions=False heading=all_reviewers %} + {% include "funds/includes/table_filter_and_search.html" with filter_form=filter_form search_term=search_term search_placeholder="reviewers" use_search=True filter_action=filter_action heading=all_reviewers %} {% render_table table %} {% endblock %} diff --git a/hypha/apply/funds/templates/funds/rounds.html b/hypha/apply/funds/templates/funds/rounds.html index 9712508e5e..9abc21a256 100644 --- a/hypha/apply/funds/templates/funds/rounds.html +++ b/hypha/apply/funds/templates/funds/rounds.html @@ -17,7 +17,7 @@ {% endadminbar %}
- {% include "funds/includes/table_filter_and_search.html" with filter_form=filter_form search_term=search_term use_batch_actions=False can_export=can_export %} + {% include "funds/includes/table_filter_and_search.html" with filter_form=filter_form search_term=search_term can_export=can_export %} {% render_table table %}
diff --git a/hypha/apply/funds/templates/funds/submissions.html b/hypha/apply/funds/templates/funds/submissions.html deleted file mode 100644 index ef41590025..0000000000 --- a/hypha/apply/funds/templates/funds/submissions.html +++ /dev/null @@ -1,45 +0,0 @@ -{% extends "funds/base_submissions_table.html" %} -{% load heroicons %} -{% load i18n static %} -{% load render_table from django_tables2 %} - -{% block title %}{% trans "Submissions" %}{% endblock %} -{% block content %} - - {% adminbar %} - {% slot header %} - {% trans "All Submissions" %} ({{ table.rows|length }}) - {% endslot %} - {% slot sub_heading %} - {% trans "Search and filter all submissions" %} • - Switch to new table view - {% endslot %} - - {% slot buttons %} - - {% heroicon_mini "queue-list" aria_hidden="true" size=16 class="inline align-text-bottom" %} - {% trans "List view" %} - - {% endslot %} - {% endadminbar %} - -
- {% if request.user.is_apply_staff %} -
-
-
-
-
-
- {% endif %} - - {% block table %} - {% include "funds/includes/table_filter_and_search.html" with filter_form=filter_form search_term=search_term use_search=True filter_action=filter_action use_batch_actions=True filter_classes="filters-open" show_archive=show_archive can_export=can_export %} - - {% render_table table %} - {% endblock %} -
-{% endblock %} diff --git a/hypha/apply/funds/templates/funds/submissions_by_round.html b/hypha/apply/funds/templates/funds/submissions_by_round.html deleted file mode 100644 index ebc84903f9..0000000000 --- a/hypha/apply/funds/templates/funds/submissions_by_round.html +++ /dev/null @@ -1,18 +0,0 @@ -{% extends "funds/base_submissions_table.html" %} -{% load i18n static %} - -{% block title %}{{ object }}{% endblock %} - -{% block content %} - - {% adminbar %} - {% slot header %}{{ object }} ({{ table.rows|length }}){% endslot %} - {% slot sub_heading %}{% if object.fund %}{{ object.fund }} | {% endif %}{% trans "Lead" %}: {{ object.lead }}{% endslot %} - {% endadminbar %} - -
- {% block table %} - {{ block.super }} - {% endblock %} -
-{% endblock %} diff --git a/hypha/apply/funds/templates/funds/submissions_by_status.html b/hypha/apply/funds/templates/funds/submissions_by_status.html deleted file mode 100644 index c99b2e14f7..0000000000 --- a/hypha/apply/funds/templates/funds/submissions_by_status.html +++ /dev/null @@ -1,21 +0,0 @@ -{% extends "funds/base_submissions_table.html" %} -{% load i18n %} - -{% block title %}{{ status }}{% endblock %} - -{% block content %} - {% adminbar %} - {% slot header %} - {{ status }} ({{ table.rows|length }}) - {% endslot %} - {% slot sub_heading %}{% trans "All submissions in " %}{{ status }}{% endslot %} - {% endadminbar %} - -
-
- {% block table %} - {{ block.super }} - {% endblock %} -
-
-{% endblock %} diff --git a/hypha/apply/funds/templates/funds/submissions_result.html b/hypha/apply/funds/templates/funds/submissions_result.html index 7e4a19092b..ac0c7df1bb 100644 --- a/hypha/apply/funds/templates/funds/submissions_result.html +++ b/hypha/apply/funds/templates/funds/submissions_result.html @@ -72,7 +72,7 @@
{% trans "Reviews" %}

{% trans "Submission value totals" %}

- {% include "funds/includes/table_filter_and_search.html" with filter_form=filter_form search_term=search_term filter_action=filter_action use_batch_actions=False filter_classes="filters-open" %} + {% include "funds/includes/table_filter_and_search.html" with filter_form=filter_form search_term=search_term filter_action=filter_action filter_classes="filters-open" %}
diff --git a/hypha/apply/funds/templates/submissions/all.html b/hypha/apply/funds/templates/submissions/all.html index 7423c954eb..82bbd53253 100644 --- a/hypha/apply/funds/templates/submissions/all.html +++ b/hypha/apply/funds/templates/submissions/all.html @@ -13,8 +13,7 @@ {% endslot %} {% slot sub_heading %} - {% trans "Search and filter all submissions" %} • - Switch to old table view + {% trans "Search and filter all submissions" %} {% endslot %} {% slot buttons %} diff --git a/hypha/apply/funds/urls.py b/hypha/apply/funds/urls.py index 7f421aecb6..121dc6887d 100644 --- a/hypha/apply/funds/urls.py +++ b/hypha/apply/funds/urls.py @@ -20,10 +20,8 @@ SubmissionDetailPDFView, SubmissionDetailView, SubmissionEditView, - SubmissionListView, SubmissionPrivateMediaView, SubmissionResultView, - SubmissionsByStatus, SubmissionSealedView, TranslateSubmissionView, UpdateLeadView, @@ -92,7 +90,6 @@ ), path("success//", submission_success, name="success"), path("all/", submissions_all, name="list"), - path("all/old/", SubmissionListView.as_view(), name="list-old"), path( "statuses/", get_applications_status_counts, @@ -274,7 +271,6 @@ "", include("hypha.apply.determinations.urls", namespace="determinations") ), path("", include("hypha.apply.flags.urls", namespace="flags")), - path("/", SubmissionsByStatus.as_view(), name="status"), ], "submissions", ) diff --git a/hypha/apply/funds/views.py b/hypha/apply/funds/views.py index 7a655967df..b97ea7f2b9 100644 --- a/hypha/apply/funds/views.py +++ b/hypha/apply/funds/views.py @@ -26,7 +26,6 @@ from django.urls import reverse_lazy from django.utils import timezone from django.utils.decorators import method_decorator -from django.utils.safestring import mark_safe from django.utils.translation import gettext as _ from django.views import View from django.views.decorators.cache import cache_page @@ -34,7 +33,6 @@ from django.views.generic import ( DeleteView, DetailView, - FormView, ListView, UpdateView, ) @@ -55,10 +53,8 @@ from hypha.apply.activity.views import ( ActivityContextMixin, CommentFormView, - DelegatedViewMixin, ) from hypha.apply.determinations.views import ( - BatchDeterminationCreateView, DeterminationCreateOrUpdateView, ) from hypha.apply.projects.forms import ProjectCreateForm @@ -75,7 +71,6 @@ from hypha.apply.utils.pdfs import draw_submission_content, make_pdf from hypha.apply.utils.storage import PrivateMediaView from hypha.apply.utils.views import ( - DelegateableListView, DelegateableView, ViewDispatcher, ) @@ -84,11 +79,6 @@ from .differ import compare from .files import generate_private_file_path from .forms import ( - BatchArchiveSubmissionForm, - BatchDeleteSubmissionForm, - BatchProgressSubmissionForm, - BatchUpdateReviewersForm, - BatchUpdateSubmissionLeadForm, CreateReminderForm, ProgressSubmissionForm, UpdateMetaTermsForm, @@ -106,37 +96,27 @@ RoundsAndLabs, ) from .permissions import ( - can_access_drafts, can_alter_archived_submissions, - can_bulk_archive_submissions, - can_export_submissions, - can_view_archived_submissions, get_archive_view_groups, has_permission, ) from .tables import ( - AdminSubmissionsTable, ReviewerLeaderboardDetailTable, ReviewerLeaderboardFilter, ReviewerLeaderboardTable, - ReviewerSubmissionsTable, RoundsFilter, RoundsTable, StaffAssignmentsTable, SubmissionFilterAndSearch, - SubmissionReviewerFilterAndSearch, ) from .utils import ( - export_submissions_to_csv, format_submission_sum_value, is_filter_empty, ) from .workflow import ( DRAFT_STATE, - PHASES_MAPPING, STAGE_CHANGE_ACTIONS, active_statuses, - review_statuses, ) if settings.APPLICATION_TRANSLATIONS_ENABLED: @@ -201,299 +181,6 @@ def get_context_data(self, **kwargs): ) -class BaseAdminSubmissionsTable(SingleTableMixin, FilterView): - table_class = AdminSubmissionsTable - filterset_class = SubmissionFilterAndSearch - filter_action = "" - search_action = "" - paginator_class = LazyPaginator - table_pagination = {"per_page": 25} - - excluded_fields = settings.SUBMISSIONS_TABLE_EXCLUDED_FIELDS - - @property - def excluded(self): - return {"exclude": self.excluded_fields} - - def get_table_kwargs(self, **kwargs): - return {**self.excluded, **kwargs} - - def get_filterset_kwargs(self, filterset_class, **kwargs): - new_kwargs = super().get_filterset_kwargs(filterset_class) - new_kwargs.update(self.excluded) - new_kwargs.update(kwargs) - return new_kwargs - - def get_queryset(self): - submissions = self.filterset_class._meta.model.objects.current().for_table( - self.request.user - ) - - if not can_access_drafts(self.request.user): - submissions = submissions.exclude_draft() - - return submissions - - def get_context_data(self, **kwargs): - search_term = self.request.GET.get("query") - - return super().get_context_data( - search_term=search_term, - search_action=self.search_action, - filter_action=self.filter_action, - can_export=can_export_submissions(self.request.user), - **kwargs, - ) - - def dispatch(self, request, *args, **kwargs): - disp = super().dispatch(request, *args, **kwargs) - if "export" in request.GET and can_export_submissions(request.user): - csv_data = export_submissions_to_csv(self.object_list) - response = HttpResponse(csv_data.readlines(), content_type="text/csv") - response["Content-Disposition"] = "attachment; filename=submissions.csv" - return response - return disp - - -@method_decorator(staff_required, name="dispatch") -class BatchUpdateLeadView(DelegatedViewMixin, FormView): - form_class = BatchUpdateSubmissionLeadForm - context_name = "batch_lead_form" - - def form_valid(self, form): - new_lead = form.cleaned_data["lead"] - submissions = form.cleaned_data["submissions"] - services.bulk_update_lead( - submissions=submissions, - user=self.request.user, - lead=new_lead, - request=self.request, - ) - return super().form_valid(form) - - def form_invalid(self, form): - messages.error( - self.request, - mark_safe(_("Sorry something went wrong") + form.errors.as_ul()), - ) - return super().form_invalid(form) - - -@method_decorator(staff_required, name="dispatch") -class BatchUpdateReviewersView(DelegatedViewMixin, FormView): - form_class = BatchUpdateReviewersForm - context_name = "batch_reviewer_form" - - def form_valid(self, form): - submissions = form.cleaned_data["submissions"] - external_reviewers = form.cleaned_data["external_reviewers"] - assigned_roles = { - role: form.cleaned_data[field] for field, role in form.role_fields.items() - } - services.bulk_update_reviewers( - submissions=submissions, - external_reviewers=external_reviewers, - assigned_roles=assigned_roles, - user=self.request.user, - request=self.request, - ) - - return super().form_valid(form) - - def form_invalid(self, form): - messages.error( - self.request, - mark_safe(_("Sorry something went wrong") + form.errors.as_ul()), - ) - return super().form_invalid(form) - - -@method_decorator(staff_required, name="dispatch") -class BatchDeleteSubmissionView(DelegatedViewMixin, FormView): - form_class = BatchDeleteSubmissionForm - context_name = "batch_delete_submission_form" - - def form_valid(self, form): - submissions = form.cleaned_data["submissions"] - services.bulk_delete_submissions( - submissions=submissions, - user=self.request.user, - request=self.request, - ) - return super().form_valid(form) - - def form_invalid(self, form): - messages.error( - self.request, - mark_safe(_("Sorry something went wrong") + form.errors.as_ul()), - ) - return super().form_invalid(form) - - -@method_decorator(staff_required, name="dispatch") -class BatchArchiveSubmissionView(DelegatedViewMixin, FormView): - form_class = BatchArchiveSubmissionForm - context_name = "batch_archive_submission_form" - - def form_valid(self, form): - # If a user without archive edit access is somehow able to access batch archive submissions - # (ie. they were looking at the submission list when permissions changed) "refresh" the page - if not can_alter_archived_submissions(self.request.user): - return HttpResponseRedirect(self.request.path) - submissions = form.cleaned_data["submissions"] - services.bulk_archive_submissions( - submissions=submissions, - user=self.request.user, - request=self.request, - ) - return super().form_valid(form) - - def form_invalid(self, form): - messages.error( - self.request, - mark_safe(_("Sorry something went wrong") + form.errors.as_ul()), - ) - return super().form_invalid(form) - - -@method_decorator(staff_required, name="dispatch") -class BatchProgressSubmissionView(DelegatedViewMixin, FormView): - form_class = BatchProgressSubmissionForm - context_name = "batch_progress_form" - - def form_valid(self, form): - submissions = form.cleaned_data["submissions"] - transitions = form.cleaned_data.get("action") - - try: - redirect = BatchDeterminationCreateView.should_redirect( - self.request, submissions, transitions - ) - except ValueError as e: - messages.warning(self.request, "Could not determine: " + str(e)) - return self.form_invalid(form) - else: - if redirect: - return redirect - - failed = [] - phase_changes = {} - for submission in submissions: - valid_actions = { - action - for action, _ in submission.get_actions_for_user(self.request.user) - } - old_phase = submission.phase - try: - transition = (valid_actions & set(transitions)).pop() - submission.perform_transition( - transition, - self.request.user, - request=self.request, - notify=False, - ) - except (PermissionDenied, KeyError): - failed.append(submission) - else: - phase_changes[submission.id] = old_phase - - if failed: - messages.warning( - self.request, - _("Failed to update: ") - + ", ".join(str(submission) for submission in failed), - ) - - succeeded_submissions = submissions.exclude( - id__in=[submission.id for submission in failed] - ) - messenger( - MESSAGES.BATCH_TRANSITION, - user=self.request.user, - request=self.request, - sources=succeeded_submissions, - related=phase_changes, - ) - - ready_for_review = [phase for phase in transitions if phase in review_statuses] - if ready_for_review: - messenger( - MESSAGES.BATCH_READY_FOR_REVIEW, - user=self.request.user, - request=self.request, - sources=succeeded_submissions.filter(status__in=ready_for_review), - ) - - return super().form_valid(form) - - -class BaseReviewerSubmissionsTable(BaseAdminSubmissionsTable): - table_class = ReviewerSubmissionsTable - filterset_class = SubmissionReviewerFilterAndSearch - - def get_queryset(self): - """ - If use_settings variable is set for ReviewerSettings use settings - parameters to filter submissions or return only reviewed_by as it - was by default. - """ - reviewer_settings = ReviewerSettings.for_request(self.request) - if reviewer_settings.use_settings: - return ( - super() - .get_queryset() - .for_reviewer_settings(self.request.user, reviewer_settings) - .order_by("-submit_time") - ) - return super().get_queryset().reviewed_by(self.request.user) - - -class SubmissionAdminListView(BaseAdminSubmissionsTable, DelegateableListView): - template_name = "funds/submissions.html" - form_views = [ - BatchUpdateLeadView, - BatchUpdateReviewersView, - BatchProgressSubmissionView, - BatchDeleteSubmissionView, - BatchArchiveSubmissionView, - ] - - def get_filterset_kwargs(self, filterset_class, **kwargs): - new_kwargs = super().get_filterset_kwargs(filterset_class) - archived_kwargs = {"archived": self.request.GET.get("archived", 0)} - new_kwargs.update(archived_kwargs) - new_kwargs.update(kwargs) - return new_kwargs - - def get_queryset(self): - if self.request.GET.get("archived"): - # if archived is in param, let archived filter handle the queryset as per its value. - submissions = ( - self.filterset_class._meta.model.objects.include_archive().for_table( - self.request.user - ) - ) - else: - submissions = self.filterset_class._meta.model.objects.current().for_table( - self.request.user - ) - - if not can_access_drafts(self.request.user): - submissions = submissions.exclude_draft() - - return submissions - - def get_context_data(self, **kwargs): - show_archive = can_view_archived_submissions(self.request.user) - can_archive = can_bulk_archive_submissions(self.request.user) - - return super().get_context_data( - show_archive=show_archive, - can_bulk_archive=can_archive, - **kwargs, - ) - - @method_decorator(staff_required, name="dispatch") class GroupingApplicationsListView(TemplateView): """ @@ -503,53 +190,6 @@ class GroupingApplicationsListView(TemplateView): template_name = "funds/grouped_application_list.html" -class SubmissionReviewerListView(BaseReviewerSubmissionsTable): - template_name = "funds/submissions.html" - - -class SubmissionListView(ViewDispatcher): - admin_view = SubmissionAdminListView - reviewer_view = SubmissionReviewerListView - - -@method_decorator(staff_required, name="dispatch") -class SubmissionsByStatus(BaseAdminSubmissionsTable, DelegateableListView): - template_name = "funds/submissions_by_status.html" - status_mapping = PHASES_MAPPING - form_views = [ - BatchUpdateLeadView, - BatchUpdateReviewersView, - BatchProgressSubmissionView, - BatchDeleteSubmissionView, - BatchArchiveSubmissionView, - ] - - def dispatch(self, request, *args, **kwargs): - self.status = kwargs.get("status") - try: - status_data = self.status_mapping[self.status] - except KeyError: - raise Http404(_("No statuses match the requested value")) from None - self.status_name = status_data["name"] - self.statuses = status_data["statuses"] - return super().dispatch(request, *args, **kwargs) - - def get_filterset_kwargs(self, filterset_class, **kwargs): - return super().get_filterset_kwargs( - filterset_class, limit_statuses=self.statuses, **kwargs - ) - - def get_queryset(self): - return super().get_queryset().filter(status__in=self.statuses) - - def get_context_data(self, **kwargs): - return super().get_context_data( - status=self.status_name, - statuses=self.statuses, - **kwargs, - ) - - @method_decorator(staff_required, name="dispatch") class ProgressSubmissionView(View): def dispatch(self, request, *args, **kwargs): diff --git a/hypha/apply/projects/forms/payment.py b/hypha/apply/projects/forms/payment.py index c830156390..1c4d67c613 100644 --- a/hypha/apply/projects/forms/payment.py +++ b/hypha/apply/projects/forms/payment.py @@ -206,9 +206,7 @@ def save(self, *args, **kwargs): class BatchUpdateInvoiceStatusForm(forms.Form): invoice_action = forms.ChoiceField(label=_("Status")) - invoices = forms.CharField( - widget=forms.HiddenInput(attrs={"class": "js-invoices-id"}) - ) + invoices = forms.CharField(widget=forms.HiddenInput(attrs={"id": "js-invoices-id"})) def __init__(self, *args, **kwargs): self.user = kwargs.pop("user") diff --git a/hypha/apply/projects/templates/application_projects/includes/batch_invoice_status_update.html b/hypha/apply/projects/templates/application_projects/includes/batch_invoice_status_update.html deleted file mode 100644 index 75120ef70d..0000000000 --- a/hypha/apply/projects/templates/application_projects/includes/batch_invoice_status_update.html +++ /dev/null @@ -1,13 +0,0 @@ -{% load i18n %} - diff --git a/hypha/apply/projects/templates/application_projects/invoice_list.html b/hypha/apply/projects/templates/application_projects/invoice_list.html index fb38c672f5..db86b8796f 100644 --- a/hypha/apply/projects/templates/application_projects/invoice_list.html +++ b/hypha/apply/projects/templates/application_projects/invoice_list.html @@ -22,7 +22,7 @@ {% if table %} {% trans "invoices" as search_placeholder %} - {% include "funds/includes/table_filter_and_search.html" with filter_form=filter_form search_term=search_term use_search=True filter_action=filter_action use_batch_actions=True project_actions=True invoice_actions=True search_placeholder=search_placeholder %} + {% include "funds/includes/table_filter_and_search.html" with filter_form=filter_form search_term=search_term use_search=True filter_action=filter_action project_actions=True invoice_batch_actions=True search_placeholder=search_placeholder %} {% render_table table %} {% else %}

{% trans "No Invoices available" %}

diff --git a/hypha/apply/projects/templates/application_projects/modals/batch_invoice_status_update.html b/hypha/apply/projects/templates/application_projects/modals/batch_invoice_status_update.html new file mode 100644 index 0000000000..bc71d5a9f7 --- /dev/null +++ b/hypha/apply/projects/templates/application_projects/modals/batch_invoice_status_update.html @@ -0,0 +1,28 @@ +{% load i18n %} +{% modal_title %}{% trans "Update Invoices Status" %}{% endmodal_title %} + +
+
+
+ {{ invoices|length }} {% trans " invoices selected" %} + +
+ {% for invoice in invoices %} + + {{ invoice.invoice_number }} + + + + + + {% endfor %} +
+ {% trans "Update status" as update %} + {% include 'funds/includes/dialog_form_base.html' with form=form value=update %} +
+ + diff --git a/hypha/apply/projects/templates/application_projects/project_list.html b/hypha/apply/projects/templates/application_projects/project_list.html index b69b3a1d8e..6e247c35fe 100644 --- a/hypha/apply/projects/templates/application_projects/project_list.html +++ b/hypha/apply/projects/templates/application_projects/project_list.html @@ -21,7 +21,7 @@
{% if table %} - {% include "funds/includes/table_filter_and_search.html" with filter_form=filter_form search_term=search_term search_placeholder="projects" use_search=True filter_action=filter_action use_batch_actions=True filter_classes="filters-open" %} + {% include "funds/includes/table_filter_and_search.html" with filter_form=filter_form search_term=search_term search_placeholder="projects" use_search=True filter_action=filter_action filter_classes="filters-open" %} {% render_table table %} {% else %}

{% trans "No Projects Available." %}

diff --git a/hypha/apply/projects/urls.py b/hypha/apply/projects/urls.py index d476b18827..9b73c7105d 100644 --- a/hypha/apply/projects/urls.py +++ b/hypha/apply/projects/urls.py @@ -3,6 +3,7 @@ from .views import ( ApproveContractView, + BatchUpdateInvoiceStatusView, CategoryTemplatePrivateMediaView, ChangeInvoiceStatusView, ChangePAFStatusView, @@ -64,6 +65,11 @@ path( "invoices/statuses/", get_invoices_status_counts, name="invoices_status_counts" ), + path( + "all/bulk_invoice_status_update/", + BatchUpdateInvoiceStatusView.as_view(), + name="bulk_invoice_status_update", + ), path( "/", include( diff --git a/hypha/apply/projects/views/__init__.py b/hypha/apply/projects/views/__init__.py index 04102602fd..08425c8656 100644 --- a/hypha/apply/projects/views/__init__.py +++ b/hypha/apply/projects/views/__init__.py @@ -1,4 +1,5 @@ from .payment import ( + BatchUpdateInvoiceStatusView, ChangeInvoiceStatusView, CreateInvoiceView, DeleteInvoiceView, @@ -71,6 +72,7 @@ "partial_contracting_documents", "get_invoices_status_counts", "get_project_status_counts", + "BatchUpdateInvoiceStatusView", "ChangeInvoiceStatusView", "ChangeProjectstatusView", "SendForApprovalView", diff --git a/hypha/apply/projects/views/payment.py b/hypha/apply/projects/views/payment.py index 522794837f..eed884bdbf 100644 --- a/hypha/apply/projects/views/payment.py +++ b/hypha/apply/projects/views/payment.py @@ -21,6 +21,9 @@ View, ) from django_filters.views import FilterView +from django_htmx.http import ( + HttpResponseClientRefresh, +) from django_tables2 import SingleTableMixin from hypha.apply.activity.messaging import MESSAGES, messenger @@ -491,40 +494,51 @@ def test_func(self): class BatchUpdateInvoiceStatusView(DelegatedViewMixin, FormView): form_class = BatchUpdateInvoiceStatusForm context_name = "batch_invoice_status_form" + template_name = "application_projects/modals/batch_invoice_status_update.html" - def form_valid(self, form): - new_status = form.cleaned_data["invoice_action"] - invoices = form.cleaned_data["invoices"] - invoices_old_statuses = {invoice: invoice.status for invoice in invoices} - batch_update_invoices_status( - invoices=invoices, - user=self.request.user, - status=new_status, + def get(self, *args, **kwargs): + selected_ids = self.request.GET.getlist("selected_ids", "") + invoices = Invoice.objects.filter(id__in=selected_ids) + form = self.form_class(user=self.request.user) + return render( + self.request, + self.template_name, + context={"form": form, "invoices": invoices}, ) - # add activity feed for batch update invoice status - projects = Project.objects.filter( - id__in=[invoice.project.id for invoice in invoices] - ) - messenger( - MESSAGES.BATCH_UPDATE_INVOICE_STATUS, - request=self.request, - user=self.request.user, - sources=projects, - related=invoices, - ) + def post(self, *args, **kwargs): + form = self.form_class(self.request.POST, user=self.request.user) + if form.is_valid(): + new_status = form.cleaned_data["invoice_action"] + invoices = form.cleaned_data["invoices"] + invoices_old_statuses = {invoice: invoice.status for invoice in invoices} + batch_update_invoices_status( + invoices=invoices, + user=self.request.user, + status=new_status, + ) - # update tasks for selected invoices - for invoice, old_status in invoices_old_statuses.items(): - handle_tasks_on_invoice_update(old_status, invoice) - return super().form_valid(form) + # add activity feed for batch update invoice status + projects = Project.objects.filter( + id__in=[invoice.project.id for invoice in invoices] + ) + messenger( + MESSAGES.BATCH_UPDATE_INVOICE_STATUS, + request=self.request, + user=self.request.user, + sources=projects, + related=invoices, + ) - def form_invalid(self, form): + # update tasks for selected invoices + for invoice, old_status in invoices_old_statuses.items(): + handle_tasks_on_invoice_update(old_status, invoice) + return HttpResponseClientRefresh() messages.error( self.request, mark_safe(_("Sorry something went wrong") + form.errors.as_ul()), ) - return super().form_invalid(form) + return HttpResponseClientRefresh() @method_decorator(staff_or_finance_required, name="dispatch") diff --git a/hypha/static_src/javascript/batch-actions.js b/hypha/static_src/javascript/batch-actions.js index e994baccd5..7033af7d81 100644 --- a/hypha/static_src/javascript/batch-actions.js +++ b/hypha/static_src/javascript/batch-actions.js @@ -3,33 +3,15 @@ const $checkbox = $(".js-batch-select"); const $allCheckboxInput = $(".js-batch-select-all"); const $batchButtons = $(".js-batch-button"); - const $batchProgress = $(".js-batch-progress"); const $batchInvoiceProgress = $(".js-batch-invoice-progress"); - const $actionOptions = $("#id_action option"); - const $actionInvoiceOptions = $("#id_invoice_action option"); const $batchTitlesList = $(".js-batch-titles"); const $batchTitleCount = $(".js-batch-title-count"); const $hiddenIDlist = $(".js-submissions-id"); const $hiddenInvoiceIDlist = $(".js-invoices-id"); - const $batchDetermineSend = $(".js-batch-determine-send"); - const $batchDetermineConfirm = $(".js-batch-determine-confirm"); - const $batchDetermineForm = $batchDetermineSend.parent("form"); const $toggleBatchList = $(".js-toggle-batch-list"); const activeClass = "batch-actions-enabled"; const closedClass = "is-closed"; - $batchDetermineSend.click(function (e) { - if (!$batchDetermineForm[0].checkValidity()) { - $batchDetermineForm.submit(); - e.preventDefault(); - } - }); - - $batchDetermineConfirm.click(function (e) { - $batchDetermineForm.find(":submit").click(); - e.preventDefault(); - }); - $(window).on("load", function () { toggleBatchActions(); updateCount(); @@ -48,7 +30,6 @@ toggleBatchActions(); updateCount(); - updateProgressButton(); updateInvoiceProgressButton(); }); @@ -64,20 +45,33 @@ resetCheckAllInput(); } - updateProgressButton(); updateInvoiceProgressButton(); }); // append selected project titles to batch update reviewer modal $batchButtons.each(function () { - $(this).click(function () { - prepareBatchListing(); + $(this).click(function (e) { + let selectedIDs = []; + e.preventDefault(); + selectedIDs = prepareBatchListing(); + + if (selectedIDs.length > 0) { + // Get the base URL from the href attribute + const baseUrl = $(this).attr("href"); + const url = new URL(baseUrl, window.location.origin); + selectedIDs.forEach(id => { + url.searchParams.append("selected_ids", id); + }); + // Send the request using htmx.ajax + htmx.ajax('GET', url.toString(), { + target: '#htmx-modal' // Optional: set the target element + }); + } else { + alert("Please select at least one item."); + } }); }); - $batchProgress.click(function () { - updateProgressButton(); - }); $batchInvoiceProgress.click(function () { updateInvoiceProgressButton(); }); @@ -107,53 +101,35 @@ let selectedIDs = []; $checkbox.filter(":checked").each(function () { - const link = $(this).parents("tr").find(".js-title").find("a"); - const href = link.attr("href"); - const title = link.text(); - - $batchTitlesList.append(` - - ${title} - - - - - - `); selectedIDs.push($(this).parents("tr").data("record-id")); }); $batchTitleCount.append(`${selectedIDs.length} submissions selected`); $hiddenIDlist.val(selectedIDs.join(",")); $hiddenInvoiceIDlist.val(selectedIDs.join(",")); + return selectedIDs; } /** * Update the invoice progress button. */ function updateInvoiceProgressButton() { - var actions = $actionInvoiceOptions - .map(function () { - return this.value; - }) - .get(); + var actions; $checkbox.filter(":checked").each(function () { let newActions = $(this) .parents("tr") .find(".js-actions") .data("actions"); - actions = actions.filter((action) => newActions.includes(action)); - }); - - $actionInvoiceOptions.each(function () { - if (!actions.includes(this.value)) { - $(this).attr("disabled", "disabled"); + // If actions is undefined (i.e., first iteration), initialize it with newActions + if (!actions) { + actions = newActions; } else { - $(this).removeAttr("disabled"); + // Filter actions to keep only items also present in newActions + actions = actions.filter((action) => newActions.includes(action)); } }); - $actionInvoiceOptions.filter(":enabled:first").prop("selected", true); - if (actions.length === 0) { + + if (!actions || actions.length === 0) { $batchInvoiceProgress.attr("disabled", "disabled"); $batchInvoiceProgress.attr( "data-tooltip", @@ -165,42 +141,6 @@ } } - /** - * Update the progress button. - */ - function updateProgressButton() { - var actions = $actionOptions - .map(function () { - return this.value; - }) - .get(); - $checkbox.filter(":checked").each(function () { - let newActions = $(this) - .parents("tr") - .find(".js-actions") - .data("actions"); - actions = actions.filter((action) => newActions.includes(action)); - }); - $actionOptions.each(function () { - if (!actions.includes(this.value)) { - $(this).attr("disabled", "disabled"); - } else { - $(this).removeAttr("disabled"); - } - }); - $actionOptions.filter(":enabled:first").prop("selected", true); - if (actions.length === 0) { - $batchProgress.attr("disabled", "disabled"); - $batchProgress.attr( - "data-tooltip", - "Status changes can't be applied to submissions with this combination of statuses" - ); - } else { - $batchProgress.removeAttr("disabled"); - $batchProgress.removeAttr("data-tooltip"); - } - } - /** * Toggle the batch actions. */ diff --git a/hypha/static_src/sass/components/_list-reveal.scss b/hypha/static_src/sass/components/_list-reveal.scss index 4679499530..aedb95c0ac 100644 --- a/hypha/static_src/sass/components/_list-reveal.scss +++ b/hypha/static_src/sass/components/_list-reveal.scss @@ -4,6 +4,7 @@ .list-reveal { $root: &; + padding-bottom: 16px; &--determination { background-color: variables.$color--white; @@ -27,7 +28,7 @@ font-weight: variables.$weight--semibold; display: flex; justify-content: space-between; - margin: 0 -24px; + margin: 0 -16px; } &--determination { From 0e268338ab2bd4c2010fb3ea61cc3459f100e9b3 Mon Sep 17 00:00:00 2001 From: sandeepsajan0 Date: Thu, 28 Nov 2024 14:03:03 +0530 Subject: [PATCH 2/8] Removed batch action test for old tables and removed adminsubmissiontable --- hypha/apply/funds/tables.py | 16 --- .../funds/tests/views/test_batch_progress.py | 131 ------------------ .../funds/tests/views/test_batch_reviewers.py | 106 -------------- 3 files changed, 253 deletions(-) delete mode 100644 hypha/apply/funds/tests/views/test_batch_progress.py delete mode 100644 hypha/apply/funds/tests/views/test_batch_reviewers.py diff --git a/hypha/apply/funds/tables.py b/hypha/apply/funds/tables.py index b5274a923d..9c7823a64f 100644 --- a/hypha/apply/funds/tables.py +++ b/hypha/apply/funds/tables.py @@ -207,22 +207,6 @@ def render_screening_status(self, value): ) -class AdminSubmissionsTable(BaseAdminSubmissionsTable): - """Adds admin only columns to the submissions table""" - - selected = LabeledCheckboxColumn( - accessor=A("pk"), - attrs={ - "input": {"class": "js-batch-select"}, - "th__input": {"class": "js-batch-select-all"}, - }, - ) - - class Meta(BaseAdminSubmissionsTable.Meta): - fields = ("selected", *BaseAdminSubmissionsTable.Meta.fields) - sequence = fields - - class SummarySubmissionsTable(BaseAdminSubmissionsTable): class Meta(BaseAdminSubmissionsTable.Meta): orderable = False diff --git a/hypha/apply/funds/tests/views/test_batch_progress.py b/hypha/apply/funds/tests/views/test_batch_progress.py deleted file mode 100644 index 0e6a2e3192..0000000000 --- a/hypha/apply/funds/tests/views/test_batch_progress.py +++ /dev/null @@ -1,131 +0,0 @@ -from unittest import mock - -from hypha.apply.determinations.tests.factories import DeterminationFactory -from hypha.apply.funds.models import ApplicationSubmission -from hypha.apply.funds.tests.factories import ( - ApplicationSubmissionFactory, - InvitedToProposalFactory, -) -from hypha.apply.users.tests.factories import ReviewerFactory, StaffFactory, UserFactory -from hypha.apply.utils.testing.tests import BaseViewTestCase - - -class BaseBatchProgressViewTestCase(BaseViewTestCase): - url_name = "funds:submissions:{}" - base_view_name = "list-old" - - def data(self, action, submissions): - return { - "form-submitted-batch_progress_form": "Update", - "action": action, - "submissions": ",".join([str(submission.id) for submission in submissions]), - } - - -class StaffTestCase(BaseBatchProgressViewTestCase): - user_factory = StaffFactory - - def test_can_progress_application(self): - submission = ApplicationSubmissionFactory() - action = "open-review" - self.post_page(data=self.data(action, [submission])) - submission = self.refresh(submission) - self.assertEqual(submission.status, "internal_review") - - def test_can_progress_multiple_applications(self): - submissions = ApplicationSubmissionFactory.create_batch(3) - action = "open-review" - self.post_page(data=self.data(action, submissions)) - - self.assertCountEqual( - [self.refresh(submission).status for submission in submissions], - ["internal_review"] * 3, - ) - - def test_cant_progress_in_incorrect_state(self): - submission = ApplicationSubmissionFactory() - action = "close-review" - self.post_page(data=self.data(action, [submission])) - submission = self.refresh(submission) - self.assertEqual(submission.status, "in_discussion") - - def test_can_progress_one_in_mixed_state(self): - bad_submission = ApplicationSubmissionFactory() - good_submission = ApplicationSubmissionFactory(status="internal_review") - action = "close-review" - self.post_page(data=self.data(action, [good_submission, bad_submission])) - good_submission = self.refresh(good_submission) - bad_submission = self.refresh(bad_submission) - self.assertEqual(bad_submission.status, "in_discussion") - self.assertEqual(good_submission.status, "post_review_discussion") - - def test_can_progress_different_states(self): - submission = ApplicationSubmissionFactory() - other_submission = InvitedToProposalFactory() - action = "open-review" - self.post_page(data=self.data(action, [submission, other_submission])) - submission = self.refresh(submission) - other_submission = self.refresh(other_submission) - self.assertEqual(submission.status, "internal_review") - self.assertEqual(other_submission.status, "proposal_internal_review") - - def test_mixed_determine_notifies(self): - submission = ApplicationSubmissionFactory() - dismissed_submission = ApplicationSubmissionFactory(status="rejected") - DeterminationFactory( - submission=dismissed_submission, rejected=True, submitted=True - ) - action = "dismiss" - response = self.post_page( - data=self.data(action, [submission, dismissed_submission]) - ) - self.assertEqual(len(response.context["messages"]), 1) - - def test_determine_redirects(self): - submission = ApplicationSubmissionFactory() - action = "dismiss" - response = self.post_page(data=self.data(action, [submission])) - redirect_url = self.url_from_pattern( - "apply:submissions:determinations:batch", absolute=False - ) - self.assertEqual( - response.request["PATH_INFO"][: len(redirect_url)], redirect_url - ) - - @mock.patch("hypha.apply.funds.views.messenger") - def test_messenger_not_called_with_failed(self, patched): - submission = ApplicationSubmissionFactory() - action = "close-review" - self.post_page(data=self.data(action, [submission])) - patched.assert_called_once() - _, _, kwargs = patched.mock_calls[0] - self.assertQuerysetEqual( - kwargs["sources"], ApplicationSubmission.objects.none() - ) - - @mock.patch("hypha.apply.funds.views.messenger") - def test_messenger_with_submission_in_review(self, patched): - submission = ApplicationSubmissionFactory() - action = "open-review" - self.post_page(data=self.data(action, [submission])) - self.assertEqual(patched.call_count, 2) - _, _, kwargs = patched.mock_calls[0] - self.assertCountEqual(kwargs["sources"], [submission]) - _, _, kwargs = patched.mock_calls[1] - self.assertCountEqual(kwargs["sources"], [submission]) - - -class ReivewersTestCase(BaseBatchProgressViewTestCase): - user_factory = ReviewerFactory - - def test_cant_post_to_page(self): - response = self.post_page() - self.assertEqual(response.status_code, 405) - - -class ApplicantTestCase(BaseBatchProgressViewTestCase): - user_factory = UserFactory - - def test_cant_access_page_to_page(self): - response = self.post_page() - self.assertEqual(response.status_code, 403) diff --git a/hypha/apply/funds/tests/views/test_batch_reviewers.py b/hypha/apply/funds/tests/views/test_batch_reviewers.py deleted file mode 100644 index d1c4d0ed96..0000000000 --- a/hypha/apply/funds/tests/views/test_batch_reviewers.py +++ /dev/null @@ -1,106 +0,0 @@ -from hypha.apply.funds.tests.factories import ( - ApplicationSubmissionFactory, - AssignedWithRoleReviewersFactory, - ReviewerRoleFactory, -) -from hypha.apply.review.tests.factories import ReviewFactory -from hypha.apply.users.tests.factories import ReviewerFactory, StaffFactory -from hypha.apply.utils.testing.tests import BaseViewTestCase - - -class BaseBatchReviewerTestCase(BaseViewTestCase): - url_name = "funds:submissions:{}" - base_view_name = "list-old" - submissions = [] - staff = None - reviewers = [] - roles = [] - - def setUp(self): - super().setUp() - self.submissions = ApplicationSubmissionFactory.create_batch(4) - self.staff = StaffFactory.create_batch(4) - self.reviewers = ReviewerFactory.create_batch(4) - self.roles = ReviewerRoleFactory.create_batch(2) - - def data(self, reviewer_roles, submissions): - data = { - "form-submitted-batch_reviewer_form": "Update", - "submissions": ",".join([str(submission.id) for submission in submissions]), - } - - data.update( - **{ - f"role_reviewer_{str(role.id)}": reviewer.id - for role, reviewer in zip(self.roles, reviewer_roles, strict=False) - } - ) - return data - - -class StaffTestCase(BaseBatchReviewerTestCase): - user_factory = StaffFactory - - def test_can_assign_role_reviewers(self): - reviewer_roles = [self.staff[0]] - submissions = self.submissions[0:2] - self.post_page(data=self.data(reviewer_roles, submissions)) - for submission in submissions: - self.assertEqual(submission.assigned.count(), 1) - self.assertEqual(submission.assigned.first().reviewer, self.staff[0]) - self.assertEqual(submission.assigned.first().role, self.roles[0]) - - def test_can_reassign_role_reviewers(self): - AssignedWithRoleReviewersFactory( - reviewer=self.staff[1], submission=self.submissions[0], role=self.roles[0] - ) - AssignedWithRoleReviewersFactory( - reviewer=self.staff[1], submission=self.submissions[1], role=self.roles[0] - ) - submissions = self.submissions[0:2] - reviewer_roles = [self.staff[0]] - self.post_page(data=self.data(reviewer_roles, submissions)) - for submission in submissions: - self.assertEqual(submission.assigned.count(), 1) - self.assertEqual(submission.assigned.first().reviewer, self.staff[0]) - self.assertEqual(submission.assigned.first().role, self.roles[0]) - - def test_can_reassign_from_other_role_reviewers(self): - AssignedWithRoleReviewersFactory( - reviewer=self.staff[0], submission=self.submissions[0], role=self.roles[1] - ) - AssignedWithRoleReviewersFactory( - reviewer=self.staff[0], submission=self.submissions[1], role=self.roles[1] - ) - submissions = self.submissions[0:2] - reviewer_roles = [self.staff[0]] - self.post_page(data=self.data(reviewer_roles, submissions)) - for submission in submissions: - self.assertEqual(submission.assigned.count(), 1) - self.assertEqual(submission.assigned.first().reviewer, self.staff[0]) - self.assertEqual(submission.assigned.first().role, self.roles[0]) - - def test_doesnt_remove_if_already_reviewed(self): - AssignedWithRoleReviewersFactory( - reviewer=self.staff[1], submission=self.submissions[0], role=self.roles[0] - ) - ReviewFactory( - author__reviewer=self.staff[1], - author__staff=True, - submission=self.submissions[0], - draft=False, - ) - ReviewFactory( - author__reviewer=self.staff[1], - author__staff=True, - submission=self.submissions[1], - draft=False, - ) - submissions = self.submissions[0:2] - reviewer_roles = [self.staff[0]] - self.post_page(data=self.data(reviewer_roles, submissions)) - for submission in submissions: - self.assertEqual(submission.assigned.count(), 2) - reviewers = submission.assigned.values_list("reviewer", flat=True) - self.assertIn(self.staff[0].pk, reviewers) - self.assertIn(self.staff[1].pk, reviewers) From 0f0366ddce47a6b472e0b99c9f387d88a985d1c7 Mon Sep 17 00:00:00 2001 From: sandeepsajan0 Date: Fri, 29 Nov 2024 16:55:20 +0530 Subject: [PATCH 3/8] Add submission id to fix submission/success/ path in middleware test --- hypha/apply/users/tests/test_middleware.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/hypha/apply/users/tests/test_middleware.py b/hypha/apply/users/tests/test_middleware.py index 21111d3cb3..01c7edfb12 100644 --- a/hypha/apply/users/tests/test_middleware.py +++ b/hypha/apply/users/tests/test_middleware.py @@ -2,6 +2,7 @@ from django.test import TestCase, override_settings from django.urls import reverse +from hypha.apply.funds.tests.factories import ApplicationSubmissionFactory from hypha.apply.users.tests.factories import UserFactory from ..middleware import TWO_FACTOR_EXEMPTED_PATH_PREFIXES @@ -37,5 +38,8 @@ def test_unverified_user_can_access_allowed_urls(self): self.client.force_login(user) for path in TWO_FACTOR_EXEMPTED_PATH_PREFIXES: + if "success" in path: + submission = ApplicationSubmissionFactory() + path = str(path) + f"{submission.id}/" response = self.client.get(path, follow=True) self.assertEqual(response.status_code, 200) From 7b3d5a7a7081db628cf91bf3879c11e8621f8714 Mon Sep 17 00:00:00 2001 From: sandeepsajan0 Date: Thu, 5 Dec 2024 17:50:07 +0530 Subject: [PATCH 4/8] Removed next path from the batch determination should_redirect url --- hypha/apply/determinations/views.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/hypha/apply/determinations/views.py b/hypha/apply/determinations/views.py index 887d775d22..e303b38c0c 100644 --- a/hypha/apply/determinations/views.py +++ b/hypha/apply/determinations/views.py @@ -1,5 +1,3 @@ -from urllib import parse - from django import forms from django.conf import settings from django.contrib import messages @@ -277,8 +275,6 @@ def should_redirect(cls, request, submissions, actions): + action + "&submissions=" + ",".join([str(submission.id) for submission in submissions]) - + "&next=" - + parse.quote_plus(request.get_full_path()), ) elif set(actions) != non_determine_states: raise ValueError("Inconsistent states provided - please talk to an admin") From b574da906e62d06d3e050be1797ec19264045f6b Mon Sep 17 00:00:00 2001 From: sandeepsajan0 Date: Thu, 5 Dec 2024 18:01:50 +0530 Subject: [PATCH 5/8] removed next path test for batch determination code --- hypha/apply/determinations/tests/test_views.py | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/hypha/apply/determinations/tests/test_views.py b/hypha/apply/determinations/tests/test_views.py index 1b10d697cf..4f81b79779 100644 --- a/hypha/apply/determinations/tests/test_views.py +++ b/hypha/apply/determinations/tests/test_views.py @@ -8,7 +8,6 @@ from hypha.apply.activity.models import Activity from hypha.apply.determinations.options import ACCEPTED, NEEDS_MORE_INFO, REJECTED from hypha.apply.determinations.views import BatchDeterminationCreateView -from hypha.apply.funds.models import ApplicationSubmission from hypha.apply.funds.tests.factories import ApplicationSubmissionFactory from hypha.apply.users.tests.factories import StaffFactory, UserFactory from hypha.apply.utils.testing import BaseViewTestCase @@ -469,19 +468,6 @@ def test_can_submit_batch_determination_more_info_comment(self): self.assertRedirects(response, self.url_from_pattern("apply:submissions:list")) - def test_sets_next_on_redirect(self): - test_path = "/a/path/?with=query&a=sting" - request = RequestFactory().get("", PATH_INFO=test_path) - redirect = BatchDeterminationCreateView.should_redirect( - request, - ApplicationSubmission.objects.none(), - ["rejected"], - ) - url = urllib.parse.urlparse(redirect.url) - query = urllib.parse.parse_qs(url.query) - next_path = urllib.parse.unquote_plus(query["next"][0]) - self.assertEqual(next_path, test_path) - def test_success_redirects_if_exists(self): test_path = "/a/path/?with=query&a=sting" view = BatchDeterminationCreateView() From 595d61cd44c10989ec11f5beef1b5e4661e2c015 Mon Sep 17 00:00:00 2001 From: sandeepsajan0 Date: Mon, 9 Dec 2024 16:58:39 +0530 Subject: [PATCH 6/8] removed fancybox --- .../batch_determination_form.html | 3 - .../applicationsubmission_admin_detail.html | 7 - .../funds/base_submissions_table.html | 3 - .../funds/grouped_application_list.html | 3 - .../funds/includes/delegated_form_base.html | 1 - .../static_src/javascript/fancybox-global.js | 33 - .../javascript/jquery.fancybox.min.js | 13 - hypha/static_src/sass/fancybox.scss | 614 ------------------ 8 files changed, 677 deletions(-) delete mode 100644 hypha/static_src/javascript/fancybox-global.js delete mode 100644 hypha/static_src/javascript/jquery.fancybox.min.js delete mode 100644 hypha/static_src/sass/fancybox.scss diff --git a/hypha/apply/determinations/templates/determinations/batch_determination_form.html b/hypha/apply/determinations/templates/determinations/batch_determination_form.html index b058c36b93..c55a3c9709 100644 --- a/hypha/apply/determinations/templates/determinations/batch_determination_form.html +++ b/hypha/apply/determinations/templates/determinations/batch_determination_form.html @@ -3,7 +3,6 @@ {% block extra_css %} {{ block.super }} - {% endblock %} {% block adminbar %} @@ -40,7 +39,5 @@ {% block extra_js %} {{ block.super }} - - {% endblock %} diff --git a/hypha/apply/funds/templates/funds/applicationsubmission_admin_detail.html b/hypha/apply/funds/templates/funds/applicationsubmission_admin_detail.html index 5bf69f9c5f..ef1d45a91e 100644 --- a/hypha/apply/funds/templates/funds/applicationsubmission_admin_detail.html +++ b/hypha/apply/funds/templates/funds/applicationsubmission_admin_detail.html @@ -1,11 +1,6 @@ {% extends "funds/applicationsubmission_detail.html" %} {% load i18n static workflow_tags review_tags determination_tags translate_tags heroicons %} -{% block extra_css %} - -{% endblock %} - - {% block sidebar_top %}