Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
7b1287e
Add archive feature to submissions
sandeepsajan0 Oct 11, 2022
b687d09
Update current submissions logic to hide archived submissions from list
sandeepsajan0 Oct 11, 2022
2864a68
Add activity's event migrations
sandeepsajan0 Oct 11, 2022
802fff7
Add archived submission list view, provide permissions only to staff …
sandeepsajan0 Oct 13, 2022
dcfd902
Resolve migrations conflicts with email digest PR
sandeepsajan0 Oct 19, 2022
f97dd48
Add active submissions view, update all submissions to active submiss…
sandeepsajan0 Oct 26, 2022
b1afa98
Add background color for archived submissions and add a toggle button…
sandeepsajan0 Nov 2, 2022
5e25acd
remove archived table and page
sandeepsajan0 Nov 2, 2022
a16a6af
fix css lint issues
sandeepsajan0 Nov 2, 2022
2ec6368
Update button text, and make archived suitable with filters
sandeepsajan0 Nov 8, 2022
c61e1c8
Update filter querysets based on archived value
sandeepsajan0 Nov 13, 2022
b98b8c4
Add activity's event migrations
sandeepsajan0 Oct 11, 2022
a347cb8
Add archived submission list view, provide permissions only to staff …
sandeepsajan0 Oct 13, 2022
b0c62a6
Resolve migrations conflicts with email digest PR
sandeepsajan0 Oct 19, 2022
1a63a1e
remove archived table and page
sandeepsajan0 Nov 2, 2022
639b55f
Refactor the filters' queryset
sandeepsajan0 Nov 14, 2022
372e0f7
Use separate methods to update filter's queryset
sandeepsajan0 Nov 15, 2022
77bc511
Update UI for show/hide archive link, remove unnecessary margin and u…
sandeepsajan0 Nov 15, 2022
5ffc524
Remove active submission view, url and template
sandeepsajan0 Nov 21, 2022
70c293f
Resolve migrations conflicts
sandeepsajan0 Nov 26, 2022
eef7a66
Fix cursor error, by removing unnecessary distinct query
sandeepsajan0 Dec 5, 2022
5e993f3
Fix batch action css issue and reviewers filterset issue
sandeepsajan0 Dec 14, 2022
6c8988c
Update migrations after rebase.
frjo Jan 9, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions hypha/apply/activity/adapters/activity_feed.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ class ActivityAdapter(AdapterBase):
MESSAGES.SKIPPED_REPORT: 'handle_skipped_report',
MESSAGES.REPORT_FREQUENCY_CHANGED: 'handle_report_frequency',
MESSAGES.BATCH_DELETE_SUBMISSION: 'handle_batch_delete_submission',
MESSAGES.BATCH_ARCHIVE_SUBMISSION: 'handle_batch_archive_submission',

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hold onto merging this as #2991 introduces changes in this.

}

def recipients(self, message_type, **kwargs):
Expand Down Expand Up @@ -111,6 +112,13 @@ def handle_batch_delete_submission(self, sources, **kwargs):
title=submissions_text
)

def handle_batch_archive_submission(self, sources, **kwargs):
submissions = sources
submissions_text = ', '.join([submission.title for submission in submissions])
return _('Successfully archived submissions: {title}').format(
title=submissions_text
)

def handle_transition(self, old_phase, source, **kwargs):
submission = source
base_message = _('Progressed from {old_display} to {new_display}')
Expand Down
8 changes: 8 additions & 0 deletions hypha/apply/activity/adapters/slack.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ class SlackAdapter(AdapterBase):
MESSAGES.BATCH_DELETE_SUBMISSION: 'handle_batch_delete_submission',
MESSAGES.STAFF_ACCOUNT_CREATED: _('{user} has created a new account for <{link}|{source}>'),
MESSAGES.STAFF_ACCOUNT_EDITED: _('{user} has edited account for <{link}|{source}> that now has following roles: {roles}'),
MESSAGES.BATCH_ARCHIVE_SUBMISSION: 'handle_batch_archive_submission',
}

def __init__(self):
Expand Down Expand Up @@ -276,6 +277,13 @@ def handle_batch_delete_submission(self, sources, links, user, **kwargs):
user=user, title=submissions_text
)

def handle_batch_archive_submission(self, sources, links, user, **kwargs):
submissions = sources
submissions_text = ', '.join([submission.title for submission in submissions])
return _('{user} has archived submissions: {title}').format(
user=user, title=submissions_text
)

def notify_reviewers(self, source, link, **kwargs):
submission = source
reviewers_to_notify = []
Expand Down
18 changes: 18 additions & 0 deletions hypha/apply/activity/migrations/0066_alter_event_type.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Generated by Django 3.2.16 on 2022-10-19 04:05

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('activity', '0065_auto_20221006_1115'),
]

operations = [
migrations.AlterField(
model_name='event',
name='type',
field=models.CharField(choices=[('UPDATE_LEAD', 'updated lead'), ('BATCH_UPDATE_LEAD', 'batch updated lead'), ('EDIT_SUBMISSION', 'edited submission'), ('APPLICANT_EDIT', 'edited applicant'), ('NEW_SUBMISSION', 'submitted new submission'), ('SCREENING', 'screened'), ('TRANSITION', 'transitioned'), ('BATCH_TRANSITION', 'batch transitioned'), ('DETERMINATION_OUTCOME', 'sent determination outcome'), ('BATCH_DETERMINATION_OUTCOME', 'sent batch determination outcome'), ('INVITED_TO_PROPOSAL', 'invited to proposal'), ('REVIEWERS_UPDATED', 'updated reviewers'), ('BATCH_REVIEWERS_UPDATED', 'batch updated reviewers'), ('PARTNERS_UPDATED', 'updated partners'), ('PARTNERS_UPDATED_PARTNER', 'partners updated partner'), ('READY_FOR_REVIEW', 'marked ready for review'), ('BATCH_READY_FOR_REVIEW', 'marked batch ready for review'), ('NEW_REVIEW', 'added new review'), ('COMMENT', 'added comment'), ('PROPOSAL_SUBMITTED', 'submitted proposal'), ('OPENED_SEALED', 'opened sealed submission'), ('REVIEW_OPINION', 'reviewed opinion'), ('DELETE_SUBMISSION', 'deleted submission'), ('DELETE_REVIEW', 'deleted review'), ('CREATED_PROJECT', 'created project'), ('UPDATED_VENDOR', 'updated contracting information'), ('UPDATE_PROJECT_LEAD', 'updated project lead'), ('EDIT_REVIEW', 'edited review'), ('SEND_FOR_APPROVAL', 'sent for approval'), ('APPROVE_PROJECT', 'approved project'), ('PROJECT_FINAL_APPROVAL', 'sent project for final approval'), ('PROJECT_TRANSITION', 'transitioned project'), ('REQUEST_PROJECT_CHANGE', 'requested project change'), ('UPLOAD_DOCUMENT', 'uploaded document to project'), ('REMOVE_DOCUMENT', 'removed document from project'), ('UPLOAD_CONTRACT', 'uploaded contract to project'), ('APPROVE_CONTRACT', 'approved contract'), ('CREATE_INVOICE', 'created invoice for project'), ('UPDATE_INVOICE_STATUS', 'updated invoice status'), ('DELETE_INVOICE', 'deleted invoice'), ('SENT_TO_COMPLIANCE', 'sent project to compliance'), ('UPDATE_INVOICE', 'updated invoice'), ('SUBMIT_REPORT', 'submitted report'), ('SKIPPED_REPORT', 'skipped report'), ('REPORT_FREQUENCY_CHANGED', 'changed report frequency'), ('REPORT_NOTIFY', 'notified report'), ('CREATE_REMINDER', 'created reminder'), ('DELETE_REMINDER', 'deleted reminder'), ('REVIEW_REMINDER', 'reminder to review'), ('BATCH_DELETE_SUBMISSION', 'batch deleted submissions'), ('BATCH_ARCHIVE_SUBMISSION', 'batch archive submissions'), ('STAFF_ACCOUNT_CREATED', 'created new account'), ('STAFF_ACCOUNT_EDITED', 'edited account')], max_length=50, verbose_name='verb'),
),
]
1 change: 1 addition & 0 deletions hypha/apply/activity/options.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,5 +54,6 @@ class MESSAGES(TextChoices):
DELETE_REMINDER = 'DELETE_REMINDER', _('deleted reminder')
REVIEW_REMINDER = 'REVIEW_REMINDER', _('reminder to review')
BATCH_DELETE_SUBMISSION = 'BATCH_DELETE_SUBMISSION', _('batch deleted submissions')
BATCH_ARCHIVE_SUBMISSION = 'BATCH_ARCHIVE_SUBMISSION', _('batch archive submissions')
STAFF_ACCOUNT_CREATED = 'STAFF_ACCOUNT_CREATED', _('created new account')
STAFF_ACCOUNT_EDITED = 'STAFF_ACCOUNT_EDITED', _('edited account')
18 changes: 18 additions & 0 deletions hypha/apply/funds/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,24 @@ def save(self):
return None


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)

def save(self):
submissions = self.cleaned_data['submissions']
submissions.update(is_archive=True)
return None


class UpdateReviewersForm(ApplicationSubmissionModelForm):
reviewer_reviewers = forms.ModelMultipleChoiceField(
queryset=User.objects.reviewers().only('pk', 'full_name'),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Generated by Django 3.2.16 on 2022-11-26 11:54

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('funds', '0105_applicationbase_activity_digest_recipient_emails'),
]

operations = [
migrations.AddField(
model_name='applicationsubmission',
name='is_archive',
field=models.BooleanField(default=False),
),
]
16 changes: 13 additions & 3 deletions hypha/apply/funds/models/submissions.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,10 +109,10 @@ class ApplicationSubmissionQueryset(JSONOrderable):
json_field = 'form_data'

def active(self):
return self.filter(status__in=active_statuses)
return self.filter(status__in=active_statuses, is_archive=False)

def inactive(self):
return self.exclude(status__in=active_statuses)
return self.exclude(Q(status__in=active_statuses) | Q(is_archive=True))

def in_community_review(self, user):
qs = self.filter(
Expand Down Expand Up @@ -179,7 +179,14 @@ def undetermined(self):
return self.exclude(pk__in=determined_submissions)

def current(self):
# Applications which have the current stage active (have not been progressed)
# Applications which have the current stage active (have not been progressed) or not archived yet.
return self.exclude(Q(next__isnull=False) | Q(is_archive=True))

def archived(self):
return self.filter(is_archive=True)

def include_archive(self):
# Show all submissions( current submissions + archived submissions)
return self.exclude(next__isnull=False)

def current_accepted(self):
Expand Down Expand Up @@ -504,6 +511,9 @@ class ApplicationSubmission(
# Meta: used for migration purposes only
drupal_id = models.IntegerField(null=True, blank=True, editable=False)

# archive old submissions
is_archive = models.BooleanField(default=False)

objects = ApplicationSubmissionQueryset.as_manager()

@property
Expand Down
13 changes: 13 additions & 0 deletions hypha/apply/funds/permissions.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
from django.conf import settings


def is_user_has_access_to_view_submission(user, submission):
has_access = False

Expand All @@ -14,3 +17,13 @@ def is_user_has_access_to_view_submission(user, submission):
has_access = True

return has_access


def is_user_has_access_to_view_archived_submissions(user):
if not user.is_authenticated:
pass
elif user.is_apply_staff and settings.SUBMISSIONS_ARCHIVED_ACCESS_STAFF:
return True
elif user.is_apply_staff_admin and settings.SUBMISSIONS_ARCHIVED_ACCESS_STAFF_ADMIN:
return True
return False
55 changes: 55 additions & 0 deletions hypha/apply/funds/tables.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ class Meta:
row_attrs = {
'class': make_row_class,
'data-record-id': lambda record: record.id,
'data-archived': lambda record: record.is_archive
}
attrs = {'class': 'all-submissions-table'}
empty_text = _('No submissions available')
Expand Down Expand Up @@ -186,31 +187,60 @@ def get_used_rounds(request):
return Round.objects.filter(submissions__isnull=False).distinct()


def get_used_rounds_from_dataset(dataset):
return Round.objects.filter(id__in=dataset.values('round')).distinct()


def get_used_funds(request):
# Use page to pick up on both Labs and Funds
return Page.objects.filter(applicationsubmission__isnull=False).distinct()


def get_used_funds_from_dataset(dataset):
return Page.objects.filter(id__in=dataset.values('page')).distinct()


def get_round_leads(request):
return User.objects.filter(submission_lead__isnull=False).distinct()


def get_round_leads_from_dataset(dataset):
return User.objects.filter(id__in=dataset.values('lead')).distinct()


def get_reviewers(request):
""" All assigned reviewers, staff or admin """
return User.objects.filter(Q(submissions_reviewer__isnull=False) | Q(groups__name=STAFF_GROUP_NAME) | Q(is_superuser=True)).distinct()


def get_reviewers_from_dataset(dataset):
""" All assigned reviewers, not including Staff and Admin because we want a list of reviewers only"""
return User.objects.filter(id__in=dataset.values('reviewers')).distinct()


def get_screening_statuses(request):
return ScreeningStatus.objects.filter(
id__in=ApplicationSubmission.objects.all().values('screening_statuses__id').distinct('screening_statuses__id'))


def get_screening_statuses_from_dataset(dataset):
return ScreeningStatus.objects.filter(
id__in=dataset.values('screening_statuses__id')
).distinct()


def get_meta_terms(request):
return MetaTerm.objects.filter(
filter_on_dashboard=True,
id__in=ApplicationSubmission.objects.all().values('meta_terms__id').distinct('meta_terms__id'))


def get_meta_terms_from_dataset(dataset):
return MetaTerm.objects.filter(
filter_on_dashboard=True,
id__in=dataset.values('meta_terms__id')).distinct()


class Select2CheckboxWidgetMixin(filters.Filter):
def __init__(self, *args, **kwargs):
label = kwargs.get('label')
Expand Down Expand Up @@ -269,8 +299,26 @@ class Meta:
fields = ('status', 'fund', 'round')

def __init__(self, *args, exclude=[], limit_statuses=None, **kwargs):
qs = kwargs.get('queryset')

archived = kwargs.pop('archived') if 'archived' in kwargs.keys() else None
if archived is not None:
archived = int(archived) if archived else None

super().__init__(*args, **kwargs)

reviewers_qs = get_reviewers_from_dataset(dataset=qs.exclude(reviewers__isnull=True))
if archived is not None and archived == 0:
reviewers_qs = get_reviewers_from_dataset(dataset=qs.filter(is_archive=archived).exclude(reviewers__isnull=True))
qs = qs.filter(is_archive=archived)

self.filters['fund'].queryset = get_used_funds_from_dataset(dataset=qs)
self.filters['round'].queryset = get_used_rounds_from_dataset(dataset=qs)
self.filters['lead'].queryset = get_round_leads_from_dataset(dataset=qs)
self.filters['screening_statuses'].queryset = get_screening_statuses_from_dataset(dataset=qs)
self.filters['reviewers'].queryset = reviewers_qs
self.filters['meta_terms'].queryset = get_meta_terms_from_dataset(dataset=qs)

self.filters['status'] = StatusMultipleChoiceFilter(limit_to=limit_statuses)
self.filters['category_options'].extra['choices'] = [
(option.id, option.value)
Expand Down Expand Up @@ -315,6 +363,13 @@ def filter_category_options(self, queryset, name, value):

class SubmissionFilterAndSearch(SubmissionFilter):
query = filters.CharFilter(field_name='search_data', lookup_expr="icontains", widget=forms.HiddenInput)
archived = filters.BooleanFilter(field_name='is_archive', widget=forms.HiddenInput, method='filter_archived')

def filter_archived(self, queryset, name, value):
if not value:
# if value is 0 or None
queryset = queryset.exclude(is_archive=True)
return queryset


class SubmissionDashboardFilter(filters.FilterSet):
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{% load i18n %}
<div class="modal" id="batch-archive-submission">
<h4 class="modal__header-bar modal__header-bar--no-bottom-space">{% trans "Archive Submissions" %}</h4>
<p><strong>{% trans "Are you sure you want to archive the selected submissions?" %}</strong></p>
<div class="list-reveal">
<div class="list-reveal__item list-reveal__item--meta" aria-live="polite">
<span class="js-batch-title-count"></span>
<a href="#" class="list-reveal__link js-toggle-batch-list">{% trans "Show" %}</a>
</div>
<div class="list-reveal__list js-batch-titles is-closed" aria-live="polite"></div>
</div>
<!-- <p>{% trans "All content related to these submissions will also be archived. This includes reviews, determinations and comments" %}.</p>-->

{% trans "Archive" as archive %}
{% include 'funds/includes/delegated_form_base.html' with form=batch_archive_submission_form value=archive %}
</div>
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{% load django_tables2 i18n %}
{% load django_tables2 i18n submission_tags %}

<div class="wrapper wrapper--table-actions js-table-actions">
<div class="actions-bar">
Expand Down Expand Up @@ -41,12 +41,25 @@ <h4 class="heading heading--normal heading--no-margin">{{ heading }}</h4>
<svg class="icon icon--delete"><use xlink:href="#delete-submissions"></use></svg>
{% trans "Delete" %}
</button>

<button data-fancybox data-src="#batch-archive-submission" class="button button--action js-batch-button" type="button">
<svg class="icon icon--archive"><use xlink:href="#archive"></use></svg>
{% trans "Archive" %}
</button>
</div>
{% endif %}
</div>

{# Right #}
<div class="actions-bar__inner actions-bar__inner--right">
{% get_url_param 'archived' as archived_param %}
{% if show_archive %}
{% if archived_param == '1' %}
<a href="{% update_urlparams 'archived' '0' %}">{% trans "Hide archived" %}</a>
{% else %}
<a href="{% update_urlparams 'archived' '1' %}">{% trans "Show archived" %}</a>
{% endif %}
{% endif %}
{% if filter_classes != 'filters-open' %}
<button class="button button--filters js-toggle-filters">{% trans "Filters" %}</button>
{% endif %}
Expand All @@ -56,6 +69,7 @@ <h4 class="heading heading--normal heading--no-margin">{{ heading }}</h4>
<button class="button button--search" type="submit" aria-label="{% trans 'Search' %}">
<svg class="icon icon--magnifying-glass icon--search"><use xlink:href="#magnifying-glass"></use></svg>
</button>
<input type="hidden" value="{{ archived_param }}" name="archived">
{% trans "submissions" as submissions %}
<input class="input input--search input--secondary" type="text" placeholder="{% trans 'Search' %} {{ search_placeholder|default:submissions }}" name="query"{% if search_term %} value="{{ search_term }}"{% endif %} aria-label="{% trans 'Search input' %}">
</form>
Expand Down Expand Up @@ -87,4 +101,5 @@ <h4 class="heading heading--normal heading--no-margin">{{ heading }}</h4>
{% 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" %}
{% endif %}
5 changes: 4 additions & 1 deletion hypha/apply/funds/templates/funds/submissions.html
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{% extends "funds/base_submissions_table.html" %}
{% load i18n static %}
{% load render_table from django_tables2 %}

{% block title %}{% trans "Submissions" %}{% endblock %}
{% block content %}
Expand All @@ -15,7 +16,9 @@ <h1 class="gamma heading heading--no-margin heading--bold">{% trans "All Submiss

<div class="wrapper wrapper--large wrapper--inner-space-medium">
{% block table %}
{{ block.super }}
{% 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 %}

{% render_table table %}
{% endblock %}
</div>
{% endblock %}
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ <h4 class="heading heading--normal">{% trans "Staff Flagged Submissions" %}</h4>
{% endif %}
</div>
{% endif %}

{% endblock %}
</div>
{% endblock %}
Loading