diff --git a/hypha/apply/funds/tests/test_views.py b/hypha/apply/funds/tests/test_views.py index 3908abf8e2e61e284ed1cd6560c64d8201534f30..5e5bd2cea53ed4486aedd4cb274fb3bfda88d8fb 100644 --- a/hypha/apply/funds/tests/test_views.py +++ b/hypha/apply/funds/tests/test_views.py @@ -176,9 +176,9 @@ class TestStaffSubmissionView(BaseSubmissionViewTestCase): self.assertEqual(new_title, submission.title) def test_not_included_fields_render(self): - submission = ApplicationSubmissionFactory(form_fields__exclude__value=True) + submission = ApplicationSubmissionFactory(form_fields__exclude__checkbox=True) response = self.get_page(submission) - self.assertNotContains(response, 'Value') + self.assertNotContains(response, 'check_one') def test_can_screen_submission(self): screening_outcome = ScreeningStatusFactory() diff --git a/hypha/apply/projects/filters.py b/hypha/apply/projects/filters.py index 4917e4c273f5e335b4ea14672aef2b2922dd937e..a817fdf4df4ca861aeea068b44c8f0480313bd5a 100644 --- a/hypha/apply/projects/filters.py +++ b/hypha/apply/projects/filters.py @@ -1,6 +1,8 @@ import django_filters as filters from django import forms from django.contrib.auth import get_user_model +from django.db.models import Q +from django_select2.forms import Select2Widget from hypha.apply.funds.tables import ( Select2ModelMultipleChoiceFilter, @@ -9,6 +11,8 @@ from hypha.apply.funds.tables import ( ) from .models import ( + CLOSING, + IN_PROGRESS, PROJECT_STATUS_CHOICES, REQUEST_STATUS_CHOICES, PaymentRequest, @@ -34,15 +38,36 @@ class PaymentRequestListFilter(filters.FilterSet): class ProjectListFilter(filters.FilterSet): + REPORTING_CHOICES = ( + (0, 'Up to date'), + (1, 'Behind schedule'), + ) + fund = Select2ModelMultipleChoiceFilter(label='Funds', queryset=get_used_funds) lead = Select2ModelMultipleChoiceFilter(label='Lead', queryset=get_project_leads) status = Select2MultipleChoiceFilter(label='Status', choices=PROJECT_STATUS_CHOICES) query = filters.CharFilter(field_name='title', lookup_expr="icontains", widget=forms.HiddenInput) + reporting = filters.ChoiceFilter( + choices=REPORTING_CHOICES, + method="filter_reporting", + widget=Select2Widget(attrs={ + 'data-placeholder': 'Reporting', + 'data-minimum-results-for-search': -1, + }), + ) class Meta: fields = ['status', 'lead', 'fund'] model = Project + def filter_reporting(self, queryset, name, value): + if value == '1': + return queryset.filter(outstanding_reports__gt=0) + return queryset.filter( + Q(outstanding_reports__lt=1) | Q(outstanding_reports__isnull=True), + status__in=(IN_PROGRESS, CLOSING), + ) + class DateRangeInputWidget(filters.widgets.SuffixedMultiWidget): template_name = 'application_projects/filters/widgets/date_range_input_widget.html' diff --git a/hypha/apply/projects/forms.py b/hypha/apply/projects/forms.py index 660a2d34b82e51a06fce65bdc0e5534adb1f60ee..483f6d15eba5467fb3e2d3790c82b4960b647f9d 100644 --- a/hypha/apply/projects/forms.py +++ b/hypha/apply/projects/forms.py @@ -464,7 +464,7 @@ class ReportEditForm(forms.ModelForm): class ReportFrequencyForm(forms.ModelForm): - start = forms.DateField(label='Next report date') + start = forms.DateField(label='Starting on:') class Meta: model = ReportConfig diff --git a/hypha/apply/projects/models.py b/hypha/apply/projects/models.py index bdea1de3d0e0e6b8f28c8eb5c54c4f9f56b937ff..0acbf9a80fcd75b098b7ef72014721bdc5ca7a84 100644 --- a/hypha/apply/projects/models.py +++ b/hypha/apply/projects/models.py @@ -13,9 +13,19 @@ from django.contrib.postgres.fields import JSONField from django.core.exceptions import ValidationError from django.core.validators import MinValueValidator from django.db import models -from django.db.models import Case, ExpressionWrapper, F, Max, OuterRef, Q, Subquery, Sum -from django.db.models import Value as V -from django.db.models import When +from django.db.models import ( + Case, + Count, + ExpressionWrapper, + F, + Max, + OuterRef, + Q, + Subquery, + Sum, + Value, + When, +) from django.db.models.functions import Cast, Coalesce from django.db.models.signals import post_delete from django.dispatch.dispatcher import receiver @@ -172,7 +182,7 @@ class PaymentRequestQueryset(models.QuerySet): return self.exclude(status=DECLINED) def total_value(self, field): - return self.aggregate(total=Coalesce(Sum(field), V(0)))['total'] + return self.aggregate(total=Coalesce(Sum(field), Value(0)))['total'] def paid_value(self): return self.filter(status=PAID).total_value('paid_value') @@ -299,7 +309,7 @@ class ProjectQuerySet(models.QuerySet): def with_amount_paid(self): return self.annotate( - amount_paid=Coalesce(Sum('payment_requests__paid_value'), V(0)), + amount_paid=Coalesce(Sum('payment_requests__paid_value'), Value(0)), ) def with_last_payment(self): @@ -307,6 +317,18 @@ class ProjectQuerySet(models.QuerySet): last_payment_request=Max('payment_requests__requested_at'), ) + def with_outstanding_reports(self): + return self.annotate( + outstanding_reports=Subquery( + Report.objects.filter( + project=OuterRef('pk'), + ).to_do().order_by().values('project').annotate( + count=Count('pk'), + ).values('count'), + output_field=models.IntegerField(), + ) + ) + def with_start_date(self): return self.annotate( start=Cast( @@ -322,7 +344,7 @@ class ProjectQuerySet(models.QuerySet): ) def for_table(self): - return self.with_amount_paid().with_last_payment().select_related( + return self.with_amount_paid().with_last_payment().with_outstanding_reports().select_related( 'report_config', 'submission__page', 'lead', @@ -629,8 +651,14 @@ class ReportConfig(models.Model): def last_report(self): today = timezone.now().date() + # Get the most recent report that was either: + # - due by today and not submitted + # - was skipped but due after today + # - was submitted but due after today return self.project.reports.filter( - Q(end_date__lt=today) | Q(current__isnull=False) + Q(end_date__lt=today) | + Q(skipped=True) | + Q(submitted__isnull=False) ).first() def current_due_report(self): @@ -666,8 +694,9 @@ class ReportConfig(models.Model): report, _ = self.project.reports.update_or_create( project=self.project, - end_date__gte=today, current__isnull=True, + skipped=False, + end_date__gte=today, defaults={'end_date': next_due_date} ) return report @@ -759,6 +788,24 @@ class Report(models.Model): def get_absolute_url(self): return reverse('apply:projects:reports:detail', kwargs={'pk': self.pk}) + @property + def previous(self): + return Report.objects.submitted().filter( + project=self.project_id, + end_date__lt=self.end_date, + ).exclude( + pk=self.pk, + ).first() + + @property + def next(self): + return Report.objects.submitted().filter( + project=self.project_id, + end_date__gt=self.end_date, + ).exclude( + pk=self.pk, + ).order_by('end_date').first() + @property def past_due(self): return timezone.now().date() > self.end_date @@ -772,7 +819,7 @@ class Report(models.Model): @property def can_submit(self): - return self.start_date <= timezone.now().date() + return self.start_date <= timezone.now().date() and not self.skipped @property def submitted_date(self): diff --git a/hypha/apply/projects/tables.py b/hypha/apply/projects/tables.py index 2c86e162e6f05e8fb55c9d50aad75766d3f756a9..82219029c9501ba729357f9bf92e20f9859f1cff 100644 --- a/hypha/apply/projects/tables.py +++ b/hypha/apply/projects/tables.py @@ -77,6 +77,13 @@ class BaseProjectsTable(tables.Table): end_date = tables.DateColumn(verbose_name='End Date', accessor='proposed_end') fund_allocation = tables.Column(verbose_name='Fund Allocation', accessor='value') + def order_reporting(self, qs, is_descending): + direction = '-' if is_descending else '' + + qs = qs.order_by(f'{direction}outstanding_reports') + + return qs, True + def render_fund_allocation(self, record): return f'${intcomma(record.amount_paid)} / ${intcomma(record.value)}' diff --git a/hypha/apply/projects/templates/application_projects/filters/widgets/date_range_input_widget.html b/hypha/apply/projects/templates/application_projects/filters/widgets/date_range_input_widget.html index d498285f5c11f080e261a510ff8e8d6ce2453eb8..a00a8de20413c7f8cdd5d41b1b3976a927f7ae69 100644 --- a/hypha/apply/projects/templates/application_projects/filters/widgets/date_range_input_widget.html +++ b/hypha/apply/projects/templates/application_projects/filters/widgets/date_range_input_widget.html @@ -1,4 +1,7 @@ -{% include widget.subwidgets.0.template_name %} -<span>to:</span> -{% include widget.subwidgets.1.template_name %} +{% for widget in widget.subwidgets %} + {% include widget.template_name %} + {% if forloop.last %} + <span>to:</span> + {% endif %} +{% endfor %} diff --git a/hypha/apply/projects/templates/application_projects/includes/report_line.html b/hypha/apply/projects/templates/application_projects/includes/report_line.html index b1782b17e982d94167460efa970284d7b0d2a693..433d7ad94b2812f95afa98b43a313607e174b5d9 100644 --- a/hypha/apply/projects/templates/application_projects/includes/report_line.html +++ b/hypha/apply/projects/templates/application_projects/includes/report_line.html @@ -32,6 +32,7 @@ <p>You're skipping the report for <b>{{report.start_date}}</b> – <b>{{report.end_date}}</b></p> <p>This will result in a gap in reporting for the project. You can undo this at any time.</p> </div> + {% if not current %} <form action="{% url "apply:projects:reports:skip" pk=report.pk %}" method="post"> {% csrf_token %} <div class="modal__buttons"> @@ -39,6 +40,7 @@ <button data-fancybox-close class="button button--submit button--white">Cancel</button> </div> </form> + {% endif %} </div> {% endif %} diff --git a/hypha/apply/projects/templates/application_projects/includes/reports.html b/hypha/apply/projects/templates/application_projects/includes/reports.html index 43e6b96f5af327adfdccabd000b8dedd3296a01d..32b334d71326a8264f88070db92a4956428e7306 100644 --- a/hypha/apply/projects/templates/application_projects/includes/reports.html +++ b/hypha/apply/projects/templates/application_projects/includes/reports.html @@ -18,11 +18,11 @@ <div class="form__info-box"> <p> Next report will be due in - <b class="js-next-report-due-slot">(please choose the next report date)</b> + <b class="js-next-report-due-slot"></b> and the report period will be <b class="js-report-period-start"></b> to - <b class="js-report-period-end">(please choose the next report date)</b> + <b class="js-report-period-end"></b> and then every <b class="js-frequency-number-slot"></b> <b class="js-frequency-period-slot"></b> @@ -59,7 +59,6 @@ <tr> <th class="data-block__table-date">Period End</th> <th class="data-block__table-date">Submitted</th> - <th class="data-block__table-date">Privacy</th> <th class="data-block__table-update"></th> </tr> </thead> @@ -72,15 +71,15 @@ <td> <span class="data-block__mobile-label">Submitted: </span>{{ report.submitted_date|default:"Skipped" }} </td> - <td> - <span class="data-block__mobile-label">Privacy: </span>{% if report.public %}Public{% else %}Private{% endif %} - </td> <td class="data-block__links"> - <a class="data-block__action-link" href="{% url "apply:projects:reports:detail" pk=report.pk %}">View</a> + {% if not report.skipped %} + <a class="data-block__action-link" href="{% url "apply:projects:reports:detail" pk=report.pk %}">View</a> - {% if request.user.is_apply_staff %} - <a class="data-block__action-link" href="{% url "apply:projects:reports:edit" pk=report.pk %}">Edit</a> - {% if report.skipped %} + {% if request.user.is_apply_staff %} + <a class="data-block__action-link" href="{% url "apply:projects:reports:edit" pk=report.pk %}">Edit</a> + {% endif %} + {% else %} + {% if request.user.is_apply_staff %} <form action="{% url "apply:projects:reports:skip" pk=report.pk %}" method="post"> {% csrf_token %} <input type="submit" value="Unskip" class="btn data-block__action-link"></input> @@ -91,7 +90,7 @@ </tr> {% empty %} <tr> - <td colspan="4">No reports submitted</td> + <td colspan="3">No reports submitted</td> </tr> {% endfor %} </tbody> diff --git a/hypha/apply/projects/templates/application_projects/overview.html b/hypha/apply/projects/templates/application_projects/overview.html index e3159e8497eae29124e8a3b0b55e656e3d69955f..bf82115410ae657f52e4d20adbe86e82c1f0ae69 100644 --- a/hypha/apply/projects/templates/application_projects/overview.html +++ b/hypha/apply/projects/templates/application_projects/overview.html @@ -57,7 +57,7 @@ {% if reports.table.data %} <div class="wrapper wrapper--bottom-space"> - {% include "funds/includes/table_filter_and_search.html" with filter=reports.filterset filter_action=reports.url heading="Reports" %} + {% include "funds/includes/table_filter_and_search.html" with filter=reports.filterset filter_action=reports.url heading="Reports" filter_classes="filters--dates" %} {% render_table reports.table %} diff --git a/hypha/apply/projects/templates/application_projects/report_detail.html b/hypha/apply/projects/templates/application_projects/report_detail.html index ccd9ae0c97906186788c668e2f9505fdeb6a79eb..1a81d4dce5307127860209a0c820cc11088b6f43 100644 --- a/hypha/apply/projects/templates/application_projects/report_detail.html +++ b/hypha/apply/projects/templates/application_projects/report_detail.html @@ -14,31 +14,67 @@ </div> </div> - <div class="wrapper wrapper--form"> - {% if report.skipped %} - <h2>Report Skipped</h2> - {% else %} - <h3>Public</h3> - <div class="rich-text"> - {{ object.current.public_content|bleach|safe }} + <div class="wrapper wrapper--sidebar wrapper--outer-space-medium"> + <div class="wrapper--sidebar--inner"> + <div class="alert"> + <svg class="alert__icon"><use xlink:href="#exclamation-point"></use></svg> + <p class="alert__text">This report is for the period {{ report.start_date }} to {{ report.end_date }}</p> </div> - <h3>Private</h3> - <div class="rich-text"> - {{ object.current.private_content|bleach|safe }} - </div> - {% for file in object.current.files.all %} - {% if forloop.first %} - <h4>Files</h4> - <ul> - {% endif %} + <div class="card card--solid"> + {% if report.skipped %} + <h2>Report Skipped</h2> + {% else %} + <h4>Public Report</h4> + <div class="rich-text"> + {{ object.current.public_content|bleach|safe }} + </div> + + <h4>Private Report</h4> + <div class="rich-text"> + {{ object.current.private_content|bleach|safe }} + </div> + {% for file in object.current.files.all %} + {% if forloop.first %} + <h4>Attachements</h4> + <ul> + {% endif %} - <li><a href="{{ file.get_absolute_url }}">{{ file.filename }}</a></li> + <li><a href="{{ file.get_absolute_url }}">{{ file.filename }}</a></li> - {% if forloop.last %} - </ul> + {% if forloop.last %} + </ul> + {% endif %} + {% endfor %} {% endif %} - {% endfor %} - {% endif %} + </div> + </div> + <aside class="sidebar"> + {% if request.user.is_apply_staff or report.previous or report.next %} + <div class="sidebar__inner sidebar__inner--light-blue sidebar__inner--actions"> + {% if request.user.is_apply_staff %} + <a + class="button button--bottom-space button--primary button--full-width" + href="{% url "apply:projects:reports:edit" pk=report.pk %}"> + Edit + </a> + {% endif %} + {% if report.previous %} + <a + class="button button--bottom-space button--primary button--full-width" + href="{% url "apply:projects:reports:detail" pk=report.previous.pk %}"> + View previous report + </a> + {% endif %} + {% if report.next %} + <a + class="button button--bottom-space button--primary button--full-width" + href="{% url "apply:projects:reports:detail" pk=report.next.pk %}"> + View next report + </a> + {% endif %} + </div> + {% endif %} + </aside> </div> {% endblock %} diff --git a/hypha/apply/projects/templates/application_projects/report_form.html b/hypha/apply/projects/templates/application_projects/report_form.html index d161b86d5d75c19127145e09b1c8293f4c30a6b5..13bea5019e6c8af82f7fff1a77b8295cf050be70 100644 --- a/hypha/apply/projects/templates/application_projects/report_form.html +++ b/hypha/apply/projects/templates/application_projects/report_form.html @@ -40,7 +40,8 @@ {% endif %} {% endfor %} - <input type="submit" id="submit-report-form" class="is-hidden" /> + <input type="submit" id="submit-report-form-submit" name="submit" class="is-hidden" /> + <input type="submit" id="submit-report-form-save" name="save" class="is-hidden" /> <input data-fancybox data-src="#save-report" class="button button--submit button--top-space button--white" type="button" value="Save" /> <input data-fancybox data-src="#submit-report" class="button button--primary" type="button" value="Submit" /> @@ -52,7 +53,7 @@ </div> <div class="modal__buttons"> <button data-fancybox-close class="button button--submit button--white">Cancel</button> - <label class="button button--submit button--top-space button--primary" for="submit-report-form" tabindex="0">Save</label> + <label class="button button--submit button--top-space button--primary" for="submit-report-form-save" tabindex="0">Save</label> </div> </div> @@ -62,7 +63,7 @@ <p>Are you sure you want to submit your report?</p> <div class="modal__buttons"> <button data-fancybox-close class="button button--submit button--white">Cancel</button> - <label class="button button--submit button--top-space button--primary" for="submit-report-form" tabindex="0">Submit</label> + <label class="button button--submit button--top-space button--primary" for="submit-report-form-submit" tabindex="0">Submit</label> </div> </div> </form> diff --git a/hypha/apply/projects/tests/test_commands.py b/hypha/apply/projects/tests/test_commands.py index 685162fe7c85d3503ca2931f9cfc152ff02b8b95..e3b8852886840e943cff34558a175a8d68e1fb85 100644 --- a/hypha/apply/projects/tests/test_commands.py +++ b/hypha/apply/projects/tests/test_commands.py @@ -30,7 +30,8 @@ class TestNotifyReportDue(TestCase): end_date=config.schedule_start, ) out = StringIO() - call_command('notify_report_due', 7, stdout=out) + with self.settings(ALLOWED_HOSTS=[ApplyHomePage.objects.first().get_site().hostname]): + call_command('notify_report_due', 7, stdout=out) self.assertNotIn('Notified project', out.getvalue()) def test_dont_notify_already_notified(self): diff --git a/hypha/apply/projects/tests/test_models.py b/hypha/apply/projects/tests/test_models.py index 68e566ff24b8e703ab16876be545150347ac7b31..df06a56d5bc6e4565c3a5eba7493056575d7e219 100644 --- a/hypha/apply/projects/tests/test_models.py +++ b/hypha/apply/projects/tests/test_models.py @@ -197,6 +197,32 @@ class TestReportConfig(TestCase): self.assertEqual(next_date, self.today + delta) + def test_last_report_gets_report_in_past(self): + config = ReportConfigFactory() + past_report = ReportFactory( + project=config.project, + end_date=self.today - relativedelta(days=3), + ) + self.assertEqual(past_report, config.last_report()) + + def test_last_report_gets_submitted_report_in_past(self): + config = ReportConfigFactory() + past_report = ReportFactory( + project=config.project, + end_date=self.today - relativedelta(days=3), + is_submitted=True, + ) + self.assertEqual(past_report, config.last_report()) + + def test_last_report_gets_skipped(self): + config = ReportConfigFactory() + skipped_report = ReportFactory( + project=config.project, + end_date=self.today + relativedelta(days=3), + skipped=True, + ) + self.assertEqual(skipped_report, config.last_report()) + def test_months_always_relative(self): config = ReportConfigFactory(occurrence=2) last_report = self.today - relativedelta(day=25, months=1) @@ -226,6 +252,13 @@ class TestReportConfig(TestCase): self.assertEqual(Report.objects.count(), 1) self.assertEqual(report.end_date, self.today) + def test_no_report_creates_report_if_current_skipped(self): + config = ReportConfigFactory() + skipped_report = ReportFactory(end_date=self.today + relativedelta(days=3)) + report = config.current_due_report() + self.assertEqual(Report.objects.count(), 2) + self.assertNotEqual(skipped_report, report) + def test_no_report_schedule_in_future_creates_report(self): config = ReportConfigFactory(schedule_start=self.today + relativedelta(days=2)) report = config.current_due_report() diff --git a/hypha/apply/projects/tests/test_views.py b/hypha/apply/projects/tests/test_views.py index 7e5b1e8b9c08f919028f3d35c5444138d0280e24..c095677bc38d6980994e314a8cc2225c88f3dbdf 100644 --- a/hypha/apply/projects/tests/test_views.py +++ b/hypha/apply/projects/tests/test_views.py @@ -1428,10 +1428,10 @@ class TestStaffReportDetail(BaseViewTestCase): response = self.get_page(report) self.assertEqual(response.status_code, 200) - def test_can_access_skipped_report(self): + def test_cant_access_skipped_report(self): report = ReportFactory(skipped=True) response = self.get_page(report) - self.assertEqual(response.status_code, 200) + self.assertEqual(response.status_code, 404) def test_cant_access_draft_report(self): report = ReportFactory(is_draft=True) @@ -1483,3 +1483,49 @@ class TestApplicantReportDetail(BaseViewTestCase): report = ReportFactory(end_date=timezone.now() + relativedelta(days=1)) response = self.get_page(report) self.assertEqual(response.status_code, 404) + + +class TestSkipReport(BaseViewTestCase): + base_view_name = 'skip' + url_name = 'funds:projects:reports:{}' + user_factory = StaffFactory + + def get_kwargs(self, instance): + return { + 'pk': instance.pk, + } + + def test_can_skip_report(self): + report = ReportFactory(past_due=True) + response = self.post_page(report) + self.assertEqual(response.status_code, 200) + report.refresh_from_db() + self.assertTrue(report.skipped) + + def test_can_unskip_report(self): + report = ReportFactory(skipped=True, past_due=True) + response = self.post_page(report) + self.assertEqual(response.status_code, 200) + report.refresh_from_db() + self.assertFalse(report.skipped) + + def test_cant_skip_current_report(self): + report = ReportFactory(end_date=timezone.now() + relativedelta(days=1)) + response = self.post_page(report) + self.assertEqual(response.status_code, 200) + report.refresh_from_db() + self.assertFalse(report.skipped) + + def test_cant_skip_submitted_report(self): + report = ReportFactory(is_submitted=True) + response = self.post_page(report, data={}) + self.assertEqual(response.status_code, 200) + report.refresh_from_db() + self.assertFalse(report.skipped) + + def test_can_skip_draft_report(self): + report = ReportFactory(is_draft=True, past_due=True) + response = self.post_page(report) + self.assertEqual(response.status_code, 200) + report.refresh_from_db() + self.assertTrue(report.skipped) diff --git a/hypha/apply/projects/views/report.py b/hypha/apply/projects/views/report.py index ae27c9f8c374d48854195f8840168328c06b828f..997e4515ca9a68bb560752c014215223cdb02472 100644 --- a/hypha/apply/projects/views/report.py +++ b/hypha/apply/projects/views/report.py @@ -47,7 +47,7 @@ class ReportDetailView(ReportAccessMixin, DetailView): def dispatch(self, *args, **kwargs): report = self.get_object() - if not report.current and not report.skipped: + if not report.current or report.skipped: raise Http404 return super().dispatch(*args, **kwargs) @@ -153,7 +153,9 @@ class ReportSkipView(SingleObjectMixin, View): def post(self, *args, **kwargs): report = self.get_object() - if not report.current: + unsubmitted = not report.current + not_current = report.project.report_config.current_due_report() != report + if unsubmitted and not_current: report.skipped = not report.skipped report.save() messenger( @@ -175,7 +177,11 @@ class ReportFrequencyUpdate(DelegatedViewMixin, UpdateView): def get_form_kwargs(self): kwargs = super().get_form_kwargs() kwargs.pop('user') - kwargs['instance'] = kwargs['instance'].report_config + instance = kwargs['instance'].report_config + kwargs['instance'] = instance + kwargs['initial'] = { + 'start': instance.current_due_report().end_date, + } return kwargs def get_form(self): diff --git a/hypha/apply/stream_forms/testing/factories.py b/hypha/apply/stream_forms/testing/factories.py index 49d7c5bfc0624606b4ce67604be43418dbf354bc..8a705b5eaf61b71effab312e8e07e9986d97789d 100644 --- a/hypha/apply/stream_forms/testing/factories.py +++ b/hypha/apply/stream_forms/testing/factories.py @@ -179,7 +179,7 @@ class CheckboxFieldBlockFactory(FormFieldBlockFactory): class CheckboxesFieldBlockFactory(FormFieldBlockFactory): - checkboxes = ['check_one', 'check_two', 'check_three'] + checkboxes = ['check_multiple_one', 'check_multiple_two', 'check_multiple_three'] class Meta: model = stream_blocks.CheckboxesFieldBlock diff --git a/hypha/static_src/src/javascript/apply/report-calculator.js b/hypha/static_src/src/javascript/apply/report-calculator.js index 716ee321fec01be46aa8d3dd6e718b3ad6788fb7..d74646149d3fcd8b6ed7efd3b7b50e0f7183b37b 100644 --- a/hypha/static_src/src/javascript/apply/report-calculator.js +++ b/hypha/static_src/src/javascript/apply/report-calculator.js @@ -22,6 +22,7 @@ setProjectEnd(); setFrequency(); setReportPeriodStart(); + setReportPeriod(); // Add event listeners addFrequencyEvents(); @@ -35,6 +36,7 @@ // Set the reporting frequency function setFrequency() { + frequencyPeriodSlot.innerHTML = `${frequencyPeriodSlot.value}`; frequencyNumberSlot.innerHTML = frequencyNumberInput.value; pluraliseTimePeriod(frequencyNumberInput.value); } @@ -45,34 +47,36 @@ periodStartSlot.innerHTML = startDate.toISOString().slice(0, 10); } - function addReportPeriodEvents() { - startDateInput.oninput = e => { - // Update the reporting period end date (next report date) - periodEndSlot.innerHTML = e.target.value; - - // Update the reporting period range (next report date - today) - const daysDiff = dateDiffInDays(new Date(), new Date(e.target.value)); - const weeksAndDays = getWeeks(daysDiff); - const {weeks, days} = weeksAndDays; - const pluraliseWeeks = weeks === 1 ? '' : 's'; - const pluraliseDays = days === 1 ? '' : 's'; - - nextReportDueSlot.innerHTML = ` + function setReportPeriod() { + // Update the reporting period end date (next report date) + periodEndSlot.innerHTML = startDateInput.value; + + // Update the reporting period range (next report date - today) + const daysDiff = dateDiffInDays(new Date(), new Date(startDateInput.value)); + const weeksAndDays = getWeeks(daysDiff); + const {weeks, days} = weeksAndDays; + const pluraliseWeeks = weeks === 1 ? '' : 's'; + const pluraliseDays = days === 1 ? '' : 's'; + + nextReportDueSlot.innerHTML = ` ${weeks > 0 ? `${weeks} week${pluraliseWeeks}` : ''} ${days} day${pluraliseDays} `; + } + + function addReportPeriodEvents() { + startDateInput.oninput = () => { + setReportPeriod(); }; } // Update reporting frequency as the options are changed function addFrequencyEvents() { - frequencyNumberInput.oninput = e => { - frequencyNumberSlot.innerHTML = e.target.value; - pluraliseTimePeriod(e.target.value); + frequencyNumberInput.oninput = () => { + setFrequency(); }; - frequencyPeriodSelect.onchange = e => { - frequencyPeriodSlot.innerHTML = `${e.target.value}`; - pluraliseTimePeriod(frequencyNumberInput.value); + frequencyPeriodSelect.onchange = () => { + setFrequency(); }; } diff --git a/hypha/static_src/src/sass/apply/components/_sidebar.scss b/hypha/static_src/src/sass/apply/components/_sidebar.scss index 3b95801fd2222642a52a2aafff55ae8e1c38c503..fb6ba9ed6564ba6e52c8e7c366eb4e8b682aa908 100644 --- a/hypha/static_src/src/sass/apply/components/_sidebar.scss +++ b/hypha/static_src/src/sass/apply/components/_sidebar.scss @@ -1,7 +1,6 @@ .sidebar { @include media-query(tablet-portrait) { width: 345px; - margin: 20px 0 0; } &__inner {