From 37837f6c65d8b399c790ab2634542370d870e5bb Mon Sep 17 00:00:00 2001 From: Sandeep Chauhan <sandeepsajan0@gmail.com> Date: Thu, 13 Apr 2023 14:01:59 +0530 Subject: [PATCH] Project's improvements part2 (#3347) - Fixes #3306 - Fixes #3195 - Fixes #3319 - Fixes #3320 - Fixes #3325 - Fixes #3335 - Fixes #3327 - Partial Fixes #3331 --- hypha/apply/activity/adapters/emails.py | 6 ++ .../email/project_request_change.html | 12 +++ .../funds/includes/create_project_form.html | 3 +- hypha/apply/projects/blocks.py | 6 ++ hypha/apply/projects/forms/project.py | 2 +- ...071_add_customformfields_to_paf_and_sow.py | 36 +++++++++ .../0072_pafapprovals_approved_at.py | 18 +++++ hypha/apply/projects/models/project.py | 10 +-- hypha/apply/projects/permissions.py | 2 +- .../includes/contracting_documents.html | 78 ++++++++++--------- .../includes/invoices.html | 4 +- .../includes/report_frequency_config.html | 2 +- .../includes/report_line.html | 2 +- .../includes/supporting_documents.html | 64 +++++++-------- .../invoice_admin_detail.html | 2 +- .../application_projects/invoice_detail.html | 5 ++ .../project_admin_detail.html | 2 +- .../project_approval_detail.html | 2 +- .../project_approval_form.html | 2 +- .../application_projects/project_detail.html | 4 +- .../project_sow_detail.html | 2 +- .../application_projects/report_form.html | 4 +- .../projects/templatetags/contract_tools.py | 2 +- .../projects/templatetags/invoice_tools.py | 13 +++- .../projects/templatetags/project_tags.py | 13 +++- hypha/apply/projects/views/project.py | 12 ++- .../src/sass/apply/components/_button.scss | 4 + .../sass/apply/components/_data-block.scss | 5 +- .../sass/apply/components/_docs-block.scss | 8 +- .../src/sass/apply/components/_icon.scss | 15 +++- .../src/sass/apply/components/_modal.scss | 12 +++ hypha/templates/includes/sprites.html | 7 ++ 32 files changed, 246 insertions(+), 113 deletions(-) create mode 100644 hypha/apply/activity/templates/messages/email/project_request_change.html create mode 100644 hypha/apply/projects/blocks.py create mode 100644 hypha/apply/projects/migrations/0071_add_customformfields_to_paf_and_sow.py create mode 100644 hypha/apply/projects/migrations/0072_pafapprovals_approved_at.py diff --git a/hypha/apply/activity/adapters/emails.py b/hypha/apply/activity/adapters/emails.py index 2ccbfe5c8..6741107a2 100644 --- a/hypha/apply/activity/adapters/emails.py +++ b/hypha/apply/activity/adapters/emails.py @@ -52,6 +52,7 @@ class EmailAdapter(AdapterBase): MESSAGES.UPDATED_VENDOR: 'handle_vendor_updated', MESSAGES.SENT_TO_COMPLIANCE: 'messages/email/sent_to_compliance.html', MESSAGES.SEND_FOR_APPROVAL: 'messages/email/paf_for_approval.html', + MESSAGES.REQUEST_PROJECT_CHANGE: 'messages/email/project_request_change.html', MESSAGES.APPROVE_PAF: 'messages/email/paf_for_approval.html', MESSAGES.UPDATE_INVOICE: 'handle_invoice_updated', MESSAGES.UPDATE_INVOICE_STATUS: 'handle_invoice_status_updated', @@ -93,6 +94,8 @@ class EmailAdapter(AdapterBase): subject = _('Project is ready for invoicing: {source.title}').format(source=source) else: subject = _('Project status has changed to {source.status}: {source.title}').format(source=source) + elif message_type == MESSAGES.REQUEST_PROJECT_CHANGE: + subject = _("Project has been rejected, please update and resubmit") else: try: subject = source.page.specific.subject or _( @@ -261,6 +264,9 @@ class EmailAdapter(AdapterBase): return [next_paf_approval.user.email] return source.paf_approvals.filter(approved=False).values_list('user__email', flat=True) + if message_type == MESSAGES.REQUEST_PROJECT_CHANGE: + return [source.lead.email] + if message_type == MESSAGES.SENT_TO_COMPLIANCE: return get_compliance_email(target_user_gps=[CONTRACTING_GROUP_NAME, FINANCE_GROUP_NAME, STAFF_GROUP_NAME]) diff --git a/hypha/apply/activity/templates/messages/email/project_request_change.html b/hypha/apply/activity/templates/messages/email/project_request_change.html new file mode 100644 index 000000000..64bf7ae51 --- /dev/null +++ b/hypha/apply/activity/templates/messages/email/project_request_change.html @@ -0,0 +1,12 @@ +{% extends "messages/email/base.html" %} + +{% load i18n %} +{% block salutation %}{% endblock %} + +{% block content %} +{% trans "A Project has been rejected by PAF reviewers, please update it accordingly and resubmit it to the reviewers." %} + +{% trans "Title" %}: {{ source.title }} +{% trans "Link" %}: {{ request.scheme }}://{{ request.get_host }}{% url 'apply:projects:detail' pk=source.pk %} + +{% endblock %} diff --git a/hypha/apply/funds/templates/funds/includes/create_project_form.html b/hypha/apply/funds/templates/funds/includes/create_project_form.html index 9afdcf593..3e9b0ba55 100644 --- a/hypha/apply/funds/templates/funds/includes/create_project_form.html +++ b/hypha/apply/funds/templates/funds/includes/create_project_form.html @@ -1,9 +1,10 @@ {% load i18n %} <div class="modal" id="create-project"> - <h4 class="modal__header-bar">{% trans "Create Project" %}</h4> + <h4 class="modal__project-header-bar">{% trans "Create Project" %}</h4> <p>{% trans "This will create a new project. This cannot be undone." %}</p> <p>{% trans "A lead is required to create a project, select the lead below." %}</p> + <br> {% trans "Confirm" as confirm %} {% include 'funds/includes/delegated_form_base.html' with form=project_form value=confirm %} </div> diff --git a/hypha/apply/projects/blocks.py b/hypha/apply/projects/blocks.py new file mode 100644 index 000000000..c5378ff36 --- /dev/null +++ b/hypha/apply/projects/blocks.py @@ -0,0 +1,6 @@ +from hypha.apply.stream_forms.blocks import FormFieldsBlock +from hypha.apply.utils.blocks import CustomFormFieldsBlock + + +class ProjectApprovalFormCustomFormFieldsBlock(CustomFormFieldsBlock, FormFieldsBlock): + pass diff --git a/hypha/apply/projects/forms/project.py b/hypha/apply/projects/forms/project.py index d04d2cf93..b95088d68 100644 --- a/hypha/apply/projects/forms/project.py +++ b/hypha/apply/projects/forms/project.py @@ -66,7 +66,7 @@ class CreateProjectForm(forms.Form): widget=forms.HiddenInput(), ) - project_lead = forms.ModelChoiceField(label=_('Set Project Lead'), queryset=User.objects.all()) + project_lead = forms.ModelChoiceField(label=_('Select Project Lead'), queryset=User.objects.all()) def __init__(self, instance=None, user=None, *args, **kwargs): super().__init__(*args, **kwargs) diff --git a/hypha/apply/projects/migrations/0071_add_customformfields_to_paf_and_sow.py b/hypha/apply/projects/migrations/0071_add_customformfields_to_paf_and_sow.py new file mode 100644 index 000000000..e6a6d3898 --- /dev/null +++ b/hypha/apply/projects/migrations/0071_add_customformfields_to_paf_and_sow.py @@ -0,0 +1,36 @@ +# Generated by Django 3.2.18 on 2023-04-08 11:53 + +from django.db import migrations +import hypha.apply.stream_forms.blocks +import wagtail.blocks +import wagtail.fields + + +class Migration(migrations.Migration): + + dependencies = [ + ('application_projects', '0070_auto_20230327_1109'), + ] + + operations = [ + migrations.AlterField( + model_name='project', + name='form_fields', + field=wagtail.fields.StreamField([('text_markup', wagtail.blocks.RichTextBlock(group='Custom', label='Paragraph')), ('header_markup', wagtail.blocks.StructBlock([('heading_text', wagtail.blocks.CharBlock(form_classname='title', required=True)), ('size', wagtail.blocks.ChoiceBlock(choices=[('h2', 'H2'), ('h3', 'H3'), ('h4', 'H4')]))], group='Custom', label='Section header')), ('char', wagtail.blocks.StructBlock([('field_label', wagtail.blocks.CharBlock(label='Label')), ('help_text', wagtail.blocks.TextBlock(label='Help text', required=False)), ('help_link', wagtail.blocks.URLBlock(label='Help link', required=False)), ('required', wagtail.blocks.BooleanBlock(label='Required', required=False)), ('format', wagtail.blocks.ChoiceBlock(choices=[('email', 'Email'), ('url', 'URL')], label='Format', required=False)), ('default_value', wagtail.blocks.CharBlock(label='Default value', required=False))], group='Fields')), ('multi_inputs_char', wagtail.blocks.StructBlock([('field_label', wagtail.blocks.CharBlock(label='Label')), ('help_text', wagtail.blocks.TextBlock(label='Help text', required=False)), ('help_link', wagtail.blocks.URLBlock(label='Help link', required=False)), ('required', wagtail.blocks.BooleanBlock(label='Required', required=False)), ('format', wagtail.blocks.ChoiceBlock(choices=[('email', 'Email'), ('url', 'URL')], label='Format', required=False)), ('default_value', wagtail.blocks.CharBlock(label='Default value', required=False)), ('number_of_inputs', wagtail.blocks.IntegerBlock(default=2, label='Max number of inputs')), ('add_button_text', wagtail.blocks.CharBlock(default='Add new item', required=False))], group='Fields')), ('text', wagtail.blocks.StructBlock([('field_label', wagtail.blocks.CharBlock(label='Label')), ('help_text', wagtail.blocks.TextBlock(label='Help text', required=False)), ('help_link', wagtail.blocks.URLBlock(label='Help link', required=False)), ('required', wagtail.blocks.BooleanBlock(label='Required', required=False)), ('default_value', wagtail.blocks.TextBlock(label='Default value', required=False)), ('word_limit', wagtail.blocks.IntegerBlock(default=1000, label='Word limit'))], group='Fields')), ('number', wagtail.blocks.StructBlock([('field_label', wagtail.blocks.CharBlock(label='Label')), ('help_text', wagtail.blocks.TextBlock(label='Help text', required=False)), ('help_link', wagtail.blocks.URLBlock(label='Help link', required=False)), ('required', wagtail.blocks.BooleanBlock(label='Required', required=False)), ('default_value', wagtail.blocks.CharBlock(label='Default value', required=False))], group='Fields')), ('checkbox', wagtail.blocks.StructBlock([('field_label', wagtail.blocks.CharBlock(label='Label')), ('help_text', wagtail.blocks.TextBlock(label='Help text', required=False)), ('help_link', wagtail.blocks.URLBlock(label='Help link', required=False)), ('required', wagtail.blocks.BooleanBlock(label='Required', required=False)), ('default_value', wagtail.blocks.BooleanBlock(required=False))], group='Fields')), ('radios', wagtail.blocks.StructBlock([('field_label', wagtail.blocks.CharBlock(label='Label')), ('help_text', wagtail.blocks.TextBlock(label='Help text', required=False)), ('help_link', wagtail.blocks.URLBlock(label='Help link', required=False)), ('required', wagtail.blocks.BooleanBlock(label='Required', required=False)), ('choices', wagtail.blocks.ListBlock(wagtail.blocks.CharBlock(label='Choice')))], group='Fields')), ('dropdown', wagtail.blocks.StructBlock([('field_label', wagtail.blocks.CharBlock(label='Label')), ('help_text', wagtail.blocks.TextBlock(label='Help text', required=False)), ('help_link', wagtail.blocks.URLBlock(label='Help link', required=False)), ('required', wagtail.blocks.BooleanBlock(label='Required', required=False)), ('choices', wagtail.blocks.ListBlock(wagtail.blocks.CharBlock(label='Choice')))], group='Fields')), ('checkboxes', wagtail.blocks.StructBlock([('field_label', wagtail.blocks.CharBlock(label='Label')), ('help_text', wagtail.blocks.TextBlock(label='Help text', required=False)), ('help_link', wagtail.blocks.URLBlock(label='Help link', required=False)), ('required', wagtail.blocks.BooleanBlock(label='Required', required=False)), ('checkboxes', wagtail.blocks.ListBlock(wagtail.blocks.CharBlock(label='Checkbox')))], group='Fields')), ('date', wagtail.blocks.StructBlock([('field_label', wagtail.blocks.CharBlock(label='Label')), ('help_text', wagtail.blocks.TextBlock(label='Help text', required=False)), ('help_link', wagtail.blocks.URLBlock(label='Help link', required=False)), ('required', wagtail.blocks.BooleanBlock(label='Required', required=False)), ('default_value', wagtail.blocks.DateBlock(required=False))], group='Fields')), ('time', wagtail.blocks.StructBlock([('field_label', wagtail.blocks.CharBlock(label='Label')), ('help_text', wagtail.blocks.TextBlock(label='Help text', required=False)), ('help_link', wagtail.blocks.URLBlock(label='Help link', required=False)), ('required', wagtail.blocks.BooleanBlock(label='Required', required=False)), ('default_value', wagtail.blocks.TimeBlock(required=False))], group='Fields')), ('datetime', wagtail.blocks.StructBlock([('field_label', wagtail.blocks.CharBlock(label='Label')), ('help_text', wagtail.blocks.TextBlock(label='Help text', required=False)), ('help_link', wagtail.blocks.URLBlock(label='Help link', required=False)), ('required', wagtail.blocks.BooleanBlock(label='Required', required=False)), ('default_value', wagtail.blocks.DateTimeBlock(required=False))], group='Fields')), ('image', wagtail.blocks.StructBlock([('field_label', wagtail.blocks.CharBlock(label='Label')), ('help_text', wagtail.blocks.TextBlock(label='Help text', required=False)), ('help_link', wagtail.blocks.URLBlock(label='Help link', required=False)), ('required', wagtail.blocks.BooleanBlock(label='Required', required=False))], group='Fields')), ('file', wagtail.blocks.StructBlock([('field_label', wagtail.blocks.CharBlock(label='Label')), ('help_text', wagtail.blocks.TextBlock(label='Help text', required=False)), ('help_link', wagtail.blocks.URLBlock(label='Help link', required=False)), ('required', wagtail.blocks.BooleanBlock(label='Required', required=False))], group='Fields')), ('multi_file', wagtail.blocks.StructBlock([('field_label', wagtail.blocks.CharBlock(label='Label')), ('help_text', wagtail.blocks.TextBlock(label='Help text', required=False)), ('help_link', wagtail.blocks.URLBlock(label='Help link', required=False)), ('required', wagtail.blocks.BooleanBlock(label='Required', required=False))], group='Fields')), ('group_toggle', wagtail.blocks.StructBlock([('field_label', wagtail.blocks.CharBlock(label='Label')), ('help_text', wagtail.blocks.TextBlock(label='Help text', required=False)), ('help_link', wagtail.blocks.URLBlock(label='Help link', required=False)), ('required', wagtail.blocks.BooleanBlock(default=True, label='Required', required=False)), ('choices', wagtail.blocks.ListBlock(wagtail.blocks.CharBlock(label='Choice'), help_text='Please create only two choices for toggle. First choice will revel the group and the second hide it. Additional choices will be ignored.'))], group='Custom')), ('group_toggle_end', hypha.apply.stream_forms.blocks.GroupToggleEndBlock(group='Custom')), ('rich_text', wagtail.blocks.StructBlock([('field_label', wagtail.blocks.CharBlock(label='Label')), ('help_text', wagtail.blocks.TextBlock(label='Help text', required=False)), ('help_link', wagtail.blocks.URLBlock(label='Help link', required=False)), ('required', wagtail.blocks.BooleanBlock(label='Required', required=False)), ('default_value', wagtail.blocks.TextBlock(label='Default value', required=False)), ('word_limit', wagtail.blocks.IntegerBlock(default=1000, label='Word limit'))], group='Fields')), ('markdown_text', wagtail.blocks.StructBlock([('field_label', wagtail.blocks.CharBlock(label='Label')), ('help_text', wagtail.blocks.TextBlock(label='Help text', required=False)), ('help_link', wagtail.blocks.URLBlock(label='Help link', required=False)), ('required', wagtail.blocks.BooleanBlock(label='Required', required=False)), ('default_value', wagtail.blocks.TextBlock(label='Default value', required=False)), ('word_limit', wagtail.blocks.IntegerBlock(default=1000, label='Word limit'))], group='Fields'))], null=True, use_json_field=True), + ), + migrations.AlterField( + model_name='projectapprovalform', + name='form_fields', + field=wagtail.fields.StreamField([('text_markup', wagtail.blocks.RichTextBlock(group='Custom', label='Paragraph')), ('header_markup', wagtail.blocks.StructBlock([('heading_text', wagtail.blocks.CharBlock(form_classname='title', required=True)), ('size', wagtail.blocks.ChoiceBlock(choices=[('h2', 'H2'), ('h3', 'H3'), ('h4', 'H4')]))], group='Custom', label='Section header')), ('char', wagtail.blocks.StructBlock([('field_label', wagtail.blocks.CharBlock(label='Label')), ('help_text', wagtail.blocks.TextBlock(label='Help text', required=False)), ('help_link', wagtail.blocks.URLBlock(label='Help link', required=False)), ('required', wagtail.blocks.BooleanBlock(label='Required', required=False)), ('format', wagtail.blocks.ChoiceBlock(choices=[('email', 'Email'), ('url', 'URL')], label='Format', required=False)), ('default_value', wagtail.blocks.CharBlock(label='Default value', required=False))], group='Fields')), ('multi_inputs_char', wagtail.blocks.StructBlock([('field_label', wagtail.blocks.CharBlock(label='Label')), ('help_text', wagtail.blocks.TextBlock(label='Help text', required=False)), ('help_link', wagtail.blocks.URLBlock(label='Help link', required=False)), ('required', wagtail.blocks.BooleanBlock(label='Required', required=False)), ('format', wagtail.blocks.ChoiceBlock(choices=[('email', 'Email'), ('url', 'URL')], label='Format', required=False)), ('default_value', wagtail.blocks.CharBlock(label='Default value', required=False)), ('number_of_inputs', wagtail.blocks.IntegerBlock(default=2, label='Max number of inputs')), ('add_button_text', wagtail.blocks.CharBlock(default='Add new item', required=False))], group='Fields')), ('text', wagtail.blocks.StructBlock([('field_label', wagtail.blocks.CharBlock(label='Label')), ('help_text', wagtail.blocks.TextBlock(label='Help text', required=False)), ('help_link', wagtail.blocks.URLBlock(label='Help link', required=False)), ('required', wagtail.blocks.BooleanBlock(label='Required', required=False)), ('default_value', wagtail.blocks.TextBlock(label='Default value', required=False)), ('word_limit', wagtail.blocks.IntegerBlock(default=1000, label='Word limit'))], group='Fields')), ('number', wagtail.blocks.StructBlock([('field_label', wagtail.blocks.CharBlock(label='Label')), ('help_text', wagtail.blocks.TextBlock(label='Help text', required=False)), ('help_link', wagtail.blocks.URLBlock(label='Help link', required=False)), ('required', wagtail.blocks.BooleanBlock(label='Required', required=False)), ('default_value', wagtail.blocks.CharBlock(label='Default value', required=False))], group='Fields')), ('checkbox', wagtail.blocks.StructBlock([('field_label', wagtail.blocks.CharBlock(label='Label')), ('help_text', wagtail.blocks.TextBlock(label='Help text', required=False)), ('help_link', wagtail.blocks.URLBlock(label='Help link', required=False)), ('required', wagtail.blocks.BooleanBlock(label='Required', required=False)), ('default_value', wagtail.blocks.BooleanBlock(required=False))], group='Fields')), ('radios', wagtail.blocks.StructBlock([('field_label', wagtail.blocks.CharBlock(label='Label')), ('help_text', wagtail.blocks.TextBlock(label='Help text', required=False)), ('help_link', wagtail.blocks.URLBlock(label='Help link', required=False)), ('required', wagtail.blocks.BooleanBlock(label='Required', required=False)), ('choices', wagtail.blocks.ListBlock(wagtail.blocks.CharBlock(label='Choice')))], group='Fields')), ('dropdown', wagtail.blocks.StructBlock([('field_label', wagtail.blocks.CharBlock(label='Label')), ('help_text', wagtail.blocks.TextBlock(label='Help text', required=False)), ('help_link', wagtail.blocks.URLBlock(label='Help link', required=False)), ('required', wagtail.blocks.BooleanBlock(label='Required', required=False)), ('choices', wagtail.blocks.ListBlock(wagtail.blocks.CharBlock(label='Choice')))], group='Fields')), ('checkboxes', wagtail.blocks.StructBlock([('field_label', wagtail.blocks.CharBlock(label='Label')), ('help_text', wagtail.blocks.TextBlock(label='Help text', required=False)), ('help_link', wagtail.blocks.URLBlock(label='Help link', required=False)), ('required', wagtail.blocks.BooleanBlock(label='Required', required=False)), ('checkboxes', wagtail.blocks.ListBlock(wagtail.blocks.CharBlock(label='Checkbox')))], group='Fields')), ('date', wagtail.blocks.StructBlock([('field_label', wagtail.blocks.CharBlock(label='Label')), ('help_text', wagtail.blocks.TextBlock(label='Help text', required=False)), ('help_link', wagtail.blocks.URLBlock(label='Help link', required=False)), ('required', wagtail.blocks.BooleanBlock(label='Required', required=False)), ('default_value', wagtail.blocks.DateBlock(required=False))], group='Fields')), ('time', wagtail.blocks.StructBlock([('field_label', wagtail.blocks.CharBlock(label='Label')), ('help_text', wagtail.blocks.TextBlock(label='Help text', required=False)), ('help_link', wagtail.blocks.URLBlock(label='Help link', required=False)), ('required', wagtail.blocks.BooleanBlock(label='Required', required=False)), ('default_value', wagtail.blocks.TimeBlock(required=False))], group='Fields')), ('datetime', wagtail.blocks.StructBlock([('field_label', wagtail.blocks.CharBlock(label='Label')), ('help_text', wagtail.blocks.TextBlock(label='Help text', required=False)), ('help_link', wagtail.blocks.URLBlock(label='Help link', required=False)), ('required', wagtail.blocks.BooleanBlock(label='Required', required=False)), ('default_value', wagtail.blocks.DateTimeBlock(required=False))], group='Fields')), ('image', wagtail.blocks.StructBlock([('field_label', wagtail.blocks.CharBlock(label='Label')), ('help_text', wagtail.blocks.TextBlock(label='Help text', required=False)), ('help_link', wagtail.blocks.URLBlock(label='Help link', required=False)), ('required', wagtail.blocks.BooleanBlock(label='Required', required=False))], group='Fields')), ('file', wagtail.blocks.StructBlock([('field_label', wagtail.blocks.CharBlock(label='Label')), ('help_text', wagtail.blocks.TextBlock(label='Help text', required=False)), ('help_link', wagtail.blocks.URLBlock(label='Help link', required=False)), ('required', wagtail.blocks.BooleanBlock(label='Required', required=False))], group='Fields')), ('multi_file', wagtail.blocks.StructBlock([('field_label', wagtail.blocks.CharBlock(label='Label')), ('help_text', wagtail.blocks.TextBlock(label='Help text', required=False)), ('help_link', wagtail.blocks.URLBlock(label='Help link', required=False)), ('required', wagtail.blocks.BooleanBlock(label='Required', required=False))], group='Fields')), ('group_toggle', wagtail.blocks.StructBlock([('field_label', wagtail.blocks.CharBlock(label='Label')), ('help_text', wagtail.blocks.TextBlock(label='Help text', required=False)), ('help_link', wagtail.blocks.URLBlock(label='Help link', required=False)), ('required', wagtail.blocks.BooleanBlock(default=True, label='Required', required=False)), ('choices', wagtail.blocks.ListBlock(wagtail.blocks.CharBlock(label='Choice'), help_text='Please create only two choices for toggle. First choice will revel the group and the second hide it. Additional choices will be ignored.'))], group='Custom')), ('group_toggle_end', hypha.apply.stream_forms.blocks.GroupToggleEndBlock(group='Custom')), ('rich_text', wagtail.blocks.StructBlock([('field_label', wagtail.blocks.CharBlock(label='Label')), ('help_text', wagtail.blocks.TextBlock(label='Help text', required=False)), ('help_link', wagtail.blocks.URLBlock(label='Help link', required=False)), ('required', wagtail.blocks.BooleanBlock(label='Required', required=False)), ('default_value', wagtail.blocks.TextBlock(label='Default value', required=False)), ('word_limit', wagtail.blocks.IntegerBlock(default=1000, label='Word limit'))], group='Fields')), ('markdown_text', wagtail.blocks.StructBlock([('field_label', wagtail.blocks.CharBlock(label='Label')), ('help_text', wagtail.blocks.TextBlock(label='Help text', required=False)), ('help_link', wagtail.blocks.URLBlock(label='Help link', required=False)), ('required', wagtail.blocks.BooleanBlock(label='Required', required=False)), ('default_value', wagtail.blocks.TextBlock(label='Default value', required=False)), ('word_limit', wagtail.blocks.IntegerBlock(default=1000, label='Word limit'))], group='Fields'))], use_json_field=True), + ), + migrations.AlterField( + model_name='projectsow', + name='form_fields', + field=wagtail.fields.StreamField([('text_markup', wagtail.blocks.RichTextBlock(group='Custom', label='Paragraph')), ('header_markup', wagtail.blocks.StructBlock([('heading_text', wagtail.blocks.CharBlock(form_classname='title', required=True)), ('size', wagtail.blocks.ChoiceBlock(choices=[('h2', 'H2'), ('h3', 'H3'), ('h4', 'H4')]))], group='Custom', label='Section header')), ('char', wagtail.blocks.StructBlock([('field_label', wagtail.blocks.CharBlock(label='Label')), ('help_text', wagtail.blocks.TextBlock(label='Help text', required=False)), ('help_link', wagtail.blocks.URLBlock(label='Help link', required=False)), ('required', wagtail.blocks.BooleanBlock(label='Required', required=False)), ('format', wagtail.blocks.ChoiceBlock(choices=[('email', 'Email'), ('url', 'URL')], label='Format', required=False)), ('default_value', wagtail.blocks.CharBlock(label='Default value', required=False))], group='Fields')), ('multi_inputs_char', wagtail.blocks.StructBlock([('field_label', wagtail.blocks.CharBlock(label='Label')), ('help_text', wagtail.blocks.TextBlock(label='Help text', required=False)), ('help_link', wagtail.blocks.URLBlock(label='Help link', required=False)), ('required', wagtail.blocks.BooleanBlock(label='Required', required=False)), ('format', wagtail.blocks.ChoiceBlock(choices=[('email', 'Email'), ('url', 'URL')], label='Format', required=False)), ('default_value', wagtail.blocks.CharBlock(label='Default value', required=False)), ('number_of_inputs', wagtail.blocks.IntegerBlock(default=2, label='Max number of inputs')), ('add_button_text', wagtail.blocks.CharBlock(default='Add new item', required=False))], group='Fields')), ('text', wagtail.blocks.StructBlock([('field_label', wagtail.blocks.CharBlock(label='Label')), ('help_text', wagtail.blocks.TextBlock(label='Help text', required=False)), ('help_link', wagtail.blocks.URLBlock(label='Help link', required=False)), ('required', wagtail.blocks.BooleanBlock(label='Required', required=False)), ('default_value', wagtail.blocks.TextBlock(label='Default value', required=False)), ('word_limit', wagtail.blocks.IntegerBlock(default=1000, label='Word limit'))], group='Fields')), ('number', wagtail.blocks.StructBlock([('field_label', wagtail.blocks.CharBlock(label='Label')), ('help_text', wagtail.blocks.TextBlock(label='Help text', required=False)), ('help_link', wagtail.blocks.URLBlock(label='Help link', required=False)), ('required', wagtail.blocks.BooleanBlock(label='Required', required=False)), ('default_value', wagtail.blocks.CharBlock(label='Default value', required=False))], group='Fields')), ('checkbox', wagtail.blocks.StructBlock([('field_label', wagtail.blocks.CharBlock(label='Label')), ('help_text', wagtail.blocks.TextBlock(label='Help text', required=False)), ('help_link', wagtail.blocks.URLBlock(label='Help link', required=False)), ('required', wagtail.blocks.BooleanBlock(label='Required', required=False)), ('default_value', wagtail.blocks.BooleanBlock(required=False))], group='Fields')), ('radios', wagtail.blocks.StructBlock([('field_label', wagtail.blocks.CharBlock(label='Label')), ('help_text', wagtail.blocks.TextBlock(label='Help text', required=False)), ('help_link', wagtail.blocks.URLBlock(label='Help link', required=False)), ('required', wagtail.blocks.BooleanBlock(label='Required', required=False)), ('choices', wagtail.blocks.ListBlock(wagtail.blocks.CharBlock(label='Choice')))], group='Fields')), ('dropdown', wagtail.blocks.StructBlock([('field_label', wagtail.blocks.CharBlock(label='Label')), ('help_text', wagtail.blocks.TextBlock(label='Help text', required=False)), ('help_link', wagtail.blocks.URLBlock(label='Help link', required=False)), ('required', wagtail.blocks.BooleanBlock(label='Required', required=False)), ('choices', wagtail.blocks.ListBlock(wagtail.blocks.CharBlock(label='Choice')))], group='Fields')), ('checkboxes', wagtail.blocks.StructBlock([('field_label', wagtail.blocks.CharBlock(label='Label')), ('help_text', wagtail.blocks.TextBlock(label='Help text', required=False)), ('help_link', wagtail.blocks.URLBlock(label='Help link', required=False)), ('required', wagtail.blocks.BooleanBlock(label='Required', required=False)), ('checkboxes', wagtail.blocks.ListBlock(wagtail.blocks.CharBlock(label='Checkbox')))], group='Fields')), ('date', wagtail.blocks.StructBlock([('field_label', wagtail.blocks.CharBlock(label='Label')), ('help_text', wagtail.blocks.TextBlock(label='Help text', required=False)), ('help_link', wagtail.blocks.URLBlock(label='Help link', required=False)), ('required', wagtail.blocks.BooleanBlock(label='Required', required=False)), ('default_value', wagtail.blocks.DateBlock(required=False))], group='Fields')), ('time', wagtail.blocks.StructBlock([('field_label', wagtail.blocks.CharBlock(label='Label')), ('help_text', wagtail.blocks.TextBlock(label='Help text', required=False)), ('help_link', wagtail.blocks.URLBlock(label='Help link', required=False)), ('required', wagtail.blocks.BooleanBlock(label='Required', required=False)), ('default_value', wagtail.blocks.TimeBlock(required=False))], group='Fields')), ('datetime', wagtail.blocks.StructBlock([('field_label', wagtail.blocks.CharBlock(label='Label')), ('help_text', wagtail.blocks.TextBlock(label='Help text', required=False)), ('help_link', wagtail.blocks.URLBlock(label='Help link', required=False)), ('required', wagtail.blocks.BooleanBlock(label='Required', required=False)), ('default_value', wagtail.blocks.DateTimeBlock(required=False))], group='Fields')), ('image', wagtail.blocks.StructBlock([('field_label', wagtail.blocks.CharBlock(label='Label')), ('help_text', wagtail.blocks.TextBlock(label='Help text', required=False)), ('help_link', wagtail.blocks.URLBlock(label='Help link', required=False)), ('required', wagtail.blocks.BooleanBlock(label='Required', required=False))], group='Fields')), ('file', wagtail.blocks.StructBlock([('field_label', wagtail.blocks.CharBlock(label='Label')), ('help_text', wagtail.blocks.TextBlock(label='Help text', required=False)), ('help_link', wagtail.blocks.URLBlock(label='Help link', required=False)), ('required', wagtail.blocks.BooleanBlock(label='Required', required=False))], group='Fields')), ('multi_file', wagtail.blocks.StructBlock([('field_label', wagtail.blocks.CharBlock(label='Label')), ('help_text', wagtail.blocks.TextBlock(label='Help text', required=False)), ('help_link', wagtail.blocks.URLBlock(label='Help link', required=False)), ('required', wagtail.blocks.BooleanBlock(label='Required', required=False))], group='Fields')), ('group_toggle', wagtail.blocks.StructBlock([('field_label', wagtail.blocks.CharBlock(label='Label')), ('help_text', wagtail.blocks.TextBlock(label='Help text', required=False)), ('help_link', wagtail.blocks.URLBlock(label='Help link', required=False)), ('required', wagtail.blocks.BooleanBlock(default=True, label='Required', required=False)), ('choices', wagtail.blocks.ListBlock(wagtail.blocks.CharBlock(label='Choice'), help_text='Please create only two choices for toggle. First choice will revel the group and the second hide it. Additional choices will be ignored.'))], group='Custom')), ('group_toggle_end', hypha.apply.stream_forms.blocks.GroupToggleEndBlock(group='Custom')), ('rich_text', wagtail.blocks.StructBlock([('field_label', wagtail.blocks.CharBlock(label='Label')), ('help_text', wagtail.blocks.TextBlock(label='Help text', required=False)), ('help_link', wagtail.blocks.URLBlock(label='Help link', required=False)), ('required', wagtail.blocks.BooleanBlock(label='Required', required=False)), ('default_value', wagtail.blocks.TextBlock(label='Default value', required=False)), ('word_limit', wagtail.blocks.IntegerBlock(default=1000, label='Word limit'))], group='Fields')), ('markdown_text', wagtail.blocks.StructBlock([('field_label', wagtail.blocks.CharBlock(label='Label')), ('help_text', wagtail.blocks.TextBlock(label='Help text', required=False)), ('help_link', wagtail.blocks.URLBlock(label='Help link', required=False)), ('required', wagtail.blocks.BooleanBlock(label='Required', required=False)), ('default_value', wagtail.blocks.TextBlock(label='Default value', required=False)), ('word_limit', wagtail.blocks.IntegerBlock(default=1000, label='Word limit'))], group='Fields'))], null=True, use_json_field=True), + ), + migrations.AlterField( + model_name='projectsowform', + name='form_fields', + field=wagtail.fields.StreamField([('text_markup', wagtail.blocks.RichTextBlock(group='Custom', label='Paragraph')), ('header_markup', wagtail.blocks.StructBlock([('heading_text', wagtail.blocks.CharBlock(form_classname='title', required=True)), ('size', wagtail.blocks.ChoiceBlock(choices=[('h2', 'H2'), ('h3', 'H3'), ('h4', 'H4')]))], group='Custom', label='Section header')), ('char', wagtail.blocks.StructBlock([('field_label', wagtail.blocks.CharBlock(label='Label')), ('help_text', wagtail.blocks.TextBlock(label='Help text', required=False)), ('help_link', wagtail.blocks.URLBlock(label='Help link', required=False)), ('required', wagtail.blocks.BooleanBlock(label='Required', required=False)), ('format', wagtail.blocks.ChoiceBlock(choices=[('email', 'Email'), ('url', 'URL')], label='Format', required=False)), ('default_value', wagtail.blocks.CharBlock(label='Default value', required=False))], group='Fields')), ('multi_inputs_char', wagtail.blocks.StructBlock([('field_label', wagtail.blocks.CharBlock(label='Label')), ('help_text', wagtail.blocks.TextBlock(label='Help text', required=False)), ('help_link', wagtail.blocks.URLBlock(label='Help link', required=False)), ('required', wagtail.blocks.BooleanBlock(label='Required', required=False)), ('format', wagtail.blocks.ChoiceBlock(choices=[('email', 'Email'), ('url', 'URL')], label='Format', required=False)), ('default_value', wagtail.blocks.CharBlock(label='Default value', required=False)), ('number_of_inputs', wagtail.blocks.IntegerBlock(default=2, label='Max number of inputs')), ('add_button_text', wagtail.blocks.CharBlock(default='Add new item', required=False))], group='Fields')), ('text', wagtail.blocks.StructBlock([('field_label', wagtail.blocks.CharBlock(label='Label')), ('help_text', wagtail.blocks.TextBlock(label='Help text', required=False)), ('help_link', wagtail.blocks.URLBlock(label='Help link', required=False)), ('required', wagtail.blocks.BooleanBlock(label='Required', required=False)), ('default_value', wagtail.blocks.TextBlock(label='Default value', required=False)), ('word_limit', wagtail.blocks.IntegerBlock(default=1000, label='Word limit'))], group='Fields')), ('number', wagtail.blocks.StructBlock([('field_label', wagtail.blocks.CharBlock(label='Label')), ('help_text', wagtail.blocks.TextBlock(label='Help text', required=False)), ('help_link', wagtail.blocks.URLBlock(label='Help link', required=False)), ('required', wagtail.blocks.BooleanBlock(label='Required', required=False)), ('default_value', wagtail.blocks.CharBlock(label='Default value', required=False))], group='Fields')), ('checkbox', wagtail.blocks.StructBlock([('field_label', wagtail.blocks.CharBlock(label='Label')), ('help_text', wagtail.blocks.TextBlock(label='Help text', required=False)), ('help_link', wagtail.blocks.URLBlock(label='Help link', required=False)), ('required', wagtail.blocks.BooleanBlock(label='Required', required=False)), ('default_value', wagtail.blocks.BooleanBlock(required=False))], group='Fields')), ('radios', wagtail.blocks.StructBlock([('field_label', wagtail.blocks.CharBlock(label='Label')), ('help_text', wagtail.blocks.TextBlock(label='Help text', required=False)), ('help_link', wagtail.blocks.URLBlock(label='Help link', required=False)), ('required', wagtail.blocks.BooleanBlock(label='Required', required=False)), ('choices', wagtail.blocks.ListBlock(wagtail.blocks.CharBlock(label='Choice')))], group='Fields')), ('dropdown', wagtail.blocks.StructBlock([('field_label', wagtail.blocks.CharBlock(label='Label')), ('help_text', wagtail.blocks.TextBlock(label='Help text', required=False)), ('help_link', wagtail.blocks.URLBlock(label='Help link', required=False)), ('required', wagtail.blocks.BooleanBlock(label='Required', required=False)), ('choices', wagtail.blocks.ListBlock(wagtail.blocks.CharBlock(label='Choice')))], group='Fields')), ('checkboxes', wagtail.blocks.StructBlock([('field_label', wagtail.blocks.CharBlock(label='Label')), ('help_text', wagtail.blocks.TextBlock(label='Help text', required=False)), ('help_link', wagtail.blocks.URLBlock(label='Help link', required=False)), ('required', wagtail.blocks.BooleanBlock(label='Required', required=False)), ('checkboxes', wagtail.blocks.ListBlock(wagtail.blocks.CharBlock(label='Checkbox')))], group='Fields')), ('date', wagtail.blocks.StructBlock([('field_label', wagtail.blocks.CharBlock(label='Label')), ('help_text', wagtail.blocks.TextBlock(label='Help text', required=False)), ('help_link', wagtail.blocks.URLBlock(label='Help link', required=False)), ('required', wagtail.blocks.BooleanBlock(label='Required', required=False)), ('default_value', wagtail.blocks.DateBlock(required=False))], group='Fields')), ('time', wagtail.blocks.StructBlock([('field_label', wagtail.blocks.CharBlock(label='Label')), ('help_text', wagtail.blocks.TextBlock(label='Help text', required=False)), ('help_link', wagtail.blocks.URLBlock(label='Help link', required=False)), ('required', wagtail.blocks.BooleanBlock(label='Required', required=False)), ('default_value', wagtail.blocks.TimeBlock(required=False))], group='Fields')), ('datetime', wagtail.blocks.StructBlock([('field_label', wagtail.blocks.CharBlock(label='Label')), ('help_text', wagtail.blocks.TextBlock(label='Help text', required=False)), ('help_link', wagtail.blocks.URLBlock(label='Help link', required=False)), ('required', wagtail.blocks.BooleanBlock(label='Required', required=False)), ('default_value', wagtail.blocks.DateTimeBlock(required=False))], group='Fields')), ('image', wagtail.blocks.StructBlock([('field_label', wagtail.blocks.CharBlock(label='Label')), ('help_text', wagtail.blocks.TextBlock(label='Help text', required=False)), ('help_link', wagtail.blocks.URLBlock(label='Help link', required=False)), ('required', wagtail.blocks.BooleanBlock(label='Required', required=False))], group='Fields')), ('file', wagtail.blocks.StructBlock([('field_label', wagtail.blocks.CharBlock(label='Label')), ('help_text', wagtail.blocks.TextBlock(label='Help text', required=False)), ('help_link', wagtail.blocks.URLBlock(label='Help link', required=False)), ('required', wagtail.blocks.BooleanBlock(label='Required', required=False))], group='Fields')), ('multi_file', wagtail.blocks.StructBlock([('field_label', wagtail.blocks.CharBlock(label='Label')), ('help_text', wagtail.blocks.TextBlock(label='Help text', required=False)), ('help_link', wagtail.blocks.URLBlock(label='Help link', required=False)), ('required', wagtail.blocks.BooleanBlock(label='Required', required=False))], group='Fields')), ('group_toggle', wagtail.blocks.StructBlock([('field_label', wagtail.blocks.CharBlock(label='Label')), ('help_text', wagtail.blocks.TextBlock(label='Help text', required=False)), ('help_link', wagtail.blocks.URLBlock(label='Help link', required=False)), ('required', wagtail.blocks.BooleanBlock(default=True, label='Required', required=False)), ('choices', wagtail.blocks.ListBlock(wagtail.blocks.CharBlock(label='Choice'), help_text='Please create only two choices for toggle. First choice will revel the group and the second hide it. Additional choices will be ignored.'))], group='Custom')), ('group_toggle_end', hypha.apply.stream_forms.blocks.GroupToggleEndBlock(group='Custom')), ('rich_text', wagtail.blocks.StructBlock([('field_label', wagtail.blocks.CharBlock(label='Label')), ('help_text', wagtail.blocks.TextBlock(label='Help text', required=False)), ('help_link', wagtail.blocks.URLBlock(label='Help link', required=False)), ('required', wagtail.blocks.BooleanBlock(label='Required', required=False)), ('default_value', wagtail.blocks.TextBlock(label='Default value', required=False)), ('word_limit', wagtail.blocks.IntegerBlock(default=1000, label='Word limit'))], group='Fields')), ('markdown_text', wagtail.blocks.StructBlock([('field_label', wagtail.blocks.CharBlock(label='Label')), ('help_text', wagtail.blocks.TextBlock(label='Help text', required=False)), ('help_link', wagtail.blocks.URLBlock(label='Help link', required=False)), ('required', wagtail.blocks.BooleanBlock(label='Required', required=False)), ('default_value', wagtail.blocks.TextBlock(label='Default value', required=False)), ('word_limit', wagtail.blocks.IntegerBlock(default=1000, label='Word limit'))], group='Fields'))], use_json_field=True), + ), + ] diff --git a/hypha/apply/projects/migrations/0072_pafapprovals_approved_at.py b/hypha/apply/projects/migrations/0072_pafapprovals_approved_at.py new file mode 100644 index 000000000..7de4db389 --- /dev/null +++ b/hypha/apply/projects/migrations/0072_pafapprovals_approved_at.py @@ -0,0 +1,18 @@ +# Generated by Django 3.2.18 on 2023-04-11 05:21 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('application_projects', '0071_add_customformfields_to_paf_and_sow'), + ] + + operations = [ + migrations.AddField( + model_name='pafapprovals', + name='approved_at', + field=models.DateTimeField(blank=True, null=True), + ), + ] diff --git a/hypha/apply/projects/models/project.py b/hypha/apply/projects/models/project.py index b58709084..8b232bbaa 100644 --- a/hypha/apply/projects/models/project.py +++ b/hypha/apply/projects/models/project.py @@ -27,11 +27,11 @@ from wagtail.fields import StreamField from addressfield.fields import ADDRESS_FIELDS_ORDER from hypha.apply.funds.models.mixins import AccessFormData -from hypha.apply.stream_forms.blocks import FormFieldsBlock from hypha.apply.stream_forms.files import StreamFieldDataEncoder from hypha.apply.stream_forms.models import BaseStreamForm from hypha.apply.utils.storage import PrivateStorage +from ..blocks import ProjectApprovalFormCustomFormFieldsBlock from .vendor import Vendor logger = logging.getLogger(__name__) @@ -164,7 +164,7 @@ class Project(BaseStreamForm, AccessFormData, models.Model): status = models.TextField(choices=PROJECT_STATUS_CHOICES, default=COMMITTED) form_data = models.JSONField(encoder=StreamFieldDataEncoder, default=dict) - form_fields = StreamField(FormFieldsBlock(), null=True, use_json_field=True) + form_fields = StreamField(ProjectApprovalFormCustomFormFieldsBlock(), null=True, use_json_field=True) # tracks read/write state of the Project is_locked = models.BooleanField(default=False) @@ -398,7 +398,6 @@ class Project(BaseStreamForm, AccessFormData, models.Model): 'category': category, 'difference': difference, } - return False @property def is_in_progress(self): @@ -424,12 +423,12 @@ class Project(BaseStreamForm, AccessFormData, models.Model): class ProjectSOW(BaseStreamForm, AccessFormData, models.Model): project = models.OneToOneField(Project, related_name='sow', on_delete=models.CASCADE) form_data = models.JSONField(encoder=StreamFieldDataEncoder, default=dict) - form_fields = StreamField(FormFieldsBlock(), null=True, use_json_field=True) + form_fields = StreamField(ProjectApprovalFormCustomFormFieldsBlock(), null=True, use_json_field=True) class ProjectBaseStreamForm(BaseStreamForm, models.Model): name = models.CharField(max_length=255) - form_fields = StreamField(FormFieldsBlock()) + form_fields = StreamField(ProjectApprovalFormCustomFormFieldsBlock(), use_json_field=True) panels = [ FieldPanel('name'), @@ -502,6 +501,7 @@ class PAFApprovals(models.Model): approved = models.BooleanField(default=False) created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField() + approved_at = models.DateTimeField(null=True, blank=True) class Meta: unique_together = ['project', 'paf_reviewer_role'] diff --git a/hypha/apply/projects/permissions.py b/hypha/apply/projects/permissions.py index 6f97e2af9..400cb9781 100644 --- a/hypha/apply/projects/permissions.py +++ b/hypha/apply/projects/permissions.py @@ -44,7 +44,7 @@ def can_upload_contract(user, project, **kwargs): return False, 'Login Required' if user == project.user and project.contracts.exists(): - return True, 'Project Owner can only re-upload contract with counter-sign' + return True, 'Project Owner can only re-upload contract with countersigned' if user.is_contracting: return True, 'Contracting team can upload the contract' diff --git a/hypha/apply/projects/templates/application_projects/includes/contracting_documents.html b/hypha/apply/projects/templates/application_projects/includes/contracting_documents.html index 5cac56f9d..66330783a 100644 --- a/hypha/apply/projects/templates/application_projects/includes/contracting_documents.html +++ b/hypha/apply/projects/templates/application_projects/includes/contracting_documents.html @@ -5,18 +5,6 @@ <div class="docs-block__header" {% if collapsible_header %} x-on:click="collapsed = ! collapsed" {% endif %}> <div class="docs-block__heading" >{% trans "Contracting documents" %}</div> {% user_can_upload_contract object request.user as can_upload_contract %} - {% if can_upload_contract and user.is_contracting and not user.is_apply_staff %} - <a data-fancybox - data-src="#upload-contract" - class="button button--project-action" - href="#"> - {% if not contract %} - {% trans "Upload contract" %} - {% elif not contract.approver %} - {% trans "Reupload contract" %} - {% endif %} - </a> - {% endif %} {% user_can_submit_contract object user contract as can_submit_contract %} {% if can_submit_contract %} <a data-fancybox @@ -26,7 +14,7 @@ {% trans "Submit contract documents" %} </a> <div class="modal" id="submit-contract-documents"> - <h4 class="modal__header-bar">{% trans "Submit contracting documents" %}</h4> + <h4 class="modal__project-header-bar">{% trans "Submit contracting documents" %}</h4> <h5> {% trans "Are you sure you want to submit contracting documents?" %}</h5> <p>{% trans "Make sure you have uploaded correct contract and all required contracting documents." %}</p> {% trans "Submit" as submit %} @@ -52,25 +40,35 @@ <li class="docs-block__row"> <div class="docs-block__row-inner"> <svg class="icon docs-block__icon {% if object.submitted_contract_documents %}is-complete{% endif %}"><use xlink:href="#tick"></use></svg> - <p class="docs-block__title">{% trans "Contract" %} - <i>{% if contract.updated_at %}({{ contract.updated_at }}){% endif %}</i></p> + <p class="docs-block__title">{% trans "Contract" %}</p> </div> {% if contract_uploaded %} <div class="docs-block__row-inner"> <a class="docs-block__icon-link" href="{% url 'apply:projects:contract' pk=project.pk file_pk=contract.pk %}" target="_blank"> - {% trans "Download" %} - <svg class="icon icon--caret-down"><use xlink:href="#caret-down"></use></svg> + <svg class="icon icon--project-eye"><use xlink:href="#eye"></use></svg> + {% trans "View" %} </a> </div> + {% if contract.updated_at %} + <ul class="docs-block__document-list" style="margin-top:0;"> + <li class="docs-block__document"> + <div class="docs-block__row-inner"> + </div> + <div class="docs-block__row-inner"> + <i>{{ contract.updated_at }}</i> + </div> + </li> + </ul> + {% endif %} {% if not is_contract_approved %} - <ul class="docs-block__document-list"> + <ul class="docs-block__document-list" style="margin-top:0;"> <li class="docs-block__document"> <div class="docs-block__row-inner"> </div> <div class="docs-block__row-inner"> <a class="docs-block__icon-link" href="#communications" target="_blank"> <svg class="icon icon--info-circle"><use xlink:href="#info-circle-fill"></use></svg> - <span>{% trans "Corrections/amendments?" %}</span> + <span>{% trans "Need corrections/amendments to contract?" %}</span> </a> </div> </li> @@ -90,8 +88,8 @@ </div> {% if can_upload_contract and user.is_contracting %} <div class="docs-block__row-inner docs-block__row-inner__contract-upload-row"> - <a data-fancybox class="docs-block__icon-link" style="padding:5px" href="#" data-src="#upload-contract"> - <svg class="icon icon--arrow-up"><use xlink:href="#arrow-up"></use></svg> + <a data-fancybox class="docs-block__icon-link button--project-action" style="padding:5px" href="#" data-src="#upload-contract"> + <svg class="icon icon--arrow-up-short-bar icon--arrow-up-short-bar--contract-upload"><use xlink:href="#arrow-up-short-bar"></use></svg> {% if not contract %} {% trans "Upload" %} {% elif not contract.approver %} @@ -105,13 +103,13 @@ <li class="docs-block__document"> <div class="docs-block__row-inner"> <svg class="icon docs-block__icon {% if contract_reuploaded %}is-complete{% endif %}"><use xlink:href="#tick"></use></svg> - <p class="docs-block__title">{% trans "CounterSigned contract by Applicant/Contractor " %} + <p class="docs-block__title">{% trans "Countersigned contract by Applicant/Contractor " %} <i>{% if contract.uploaded_by_applicant_at %}({{ contract.uploaded_by_applicant_at }}){% endif %}</i></p> </div> {% if can_upload_contract and user.is_applicant %} <div class="docs-block__row-inner docs-block__row-inner__contract-upload-row"> - <a data-fancybox class="docs-block__icon-link" style="padding:5px" href="#" data-src="#upload-contract"> - <svg class="icon icon--arrow-up"><use xlink:href="#arrow-up"></use></svg> + <a data-fancybox class="docs-block__icon-link button--project-action" style="padding:5px" href="#" data-src="#upload-contract"> + <svg class="icon icon--arrow-up-short-bar icon--arrow-up-short-bar--contract-upload"><use xlink:href="#arrow-up-short-bar"></use></svg> {% if not contract.signed_by_applicant %} {% trans "Upload" %} {% elif not contract.approver %} @@ -125,7 +123,7 @@ {% endif %} </li> - {% if contract_uploaded %} + {% if contracting_documents_configured and contract_uploaded %} <li class="docs-block__row"> <div class="docs-block__row-inner"> <svg class="icon docs-block__icon{% if not remaining_contract_document_categories %} is-complete{% endif %}"> @@ -136,12 +134,12 @@ {% can_update_contracting_documents object user as can_update_documents %} {% if can_update_documents %} <div class="docs-block__row-inner"> - <a data-fancybox data-src="#upload-contracting-doc" class="docs-block__icon-link" href="#"> - <svg class="icon icon--arrow-up"><use xlink:href="#arrow-up"></use></svg> + <a data-fancybox data-src="#upload-contracting-doc" class="docs-block__icon-link" style="margin-right:0;" href="#"> + <svg class="icon icon--arrow-up-short-bar"><use xlink:href="#arrow-up-short-bar"></use></svg> {% trans "Upload new" %} </a> <div class="modal" id="upload-contracting-doc"> - <h4 class="modal__header-bar">{% trans "Upload a new document" %}</h4> + <h4 class="modal__project-header-bar">{% trans "Upload contracting documents" %}</h4> <p></p> {% trans "Submit" as submit %} {% include 'funds/includes/delegated_form_base.html' with form=contract_document_form value=submit %} @@ -149,7 +147,7 @@ </div> {% endif %} {% if remaining_contract_document_categories %} - <ul class="docs-block__document-list"> + <ul class="docs-block__document-list" style="padding-left:2.25rem;"> <li class="docs-block__document"> <div class="docs-block__document-inner"> <p> @@ -166,21 +164,25 @@ {% endif %} {% if object.contract_packet_files.exists %} - <ul class="docs-block__document-list"> + <ul class="docs-block__document-list" style="padding-left:2.25rem;"> {% for document in object.contract_packet_files.all %} <li class="docs-block__document"> <div class="docs-block__document-inner"> <p class="docs-block__document-info">{{ document.category.name }}</p> <p class="docs-block__document-info"><b>{{ document.title }}</b> - {{ document.created_at }}</p> </div> - <div class="docs-block__document-inner"> - <a class="docs-block__document-link" href="{% url 'apply:projects:contract_document' pk=object.pk file_pk=document.pk %}" target="_blank">{% trans "Download" %}</a> + <div class="docs-block__row-inner"> + <a class="docs-block__icon-link" href="{% url 'apply:projects:contract_document' pk=object.pk file_pk=document.pk %}" target="_blank"> + <svg class="icon icon--project-eye"><use xlink:href="#eye"></use></svg> + {% trans "View" %} + </a> {% if can_update_documents %} - <form method="POST" id="{{ remove_contract_document_form.name }}" class="docs-block__document-form"> + <form method="POST" id="{{ remove_contract_document_form.name }}" class="docs-block__icon-link"> + <svg class="icon icon--delete" style="margin-left:0; margin-right:2px"><use xlink:href="#delete"></use></svg> {% csrf_token %} {{ document.get_remove_form }} <input - class="button button--link" + class="button button--link button--remove" id="{{ remove_contract_document_form.name }}-submit" name="{{ form_prefix }}{{ remove_contract_document_form.name }}" type="submit" @@ -203,10 +205,10 @@ {% if can_upload_contract %} <div class="modal" id="upload-contract"> - {% if not user.is_apply_staff %} - <h4 class="modal__header-bar">{% trans "Upload Signed Contract" %}</h4> + {% if user.is_applicant %} + <h4 class="modal__project-header-bar">{% trans "Upload Countersigned Contract" %}</h4> {% else %} - <h4 class="modal__header-bar">{% trans "Upload Contract" %}</h4> + <h4 class="modal__project-header-bar">{% trans "Upload Signed Contract" %}</h4> {% endif %} <p><i><b>{% trans "The signed contract will be uploaded once you submit." %}</b></i></p> <br> @@ -217,7 +219,7 @@ {% if contract_to_approve %} <div class="modal" id="approve-contract"> - <h4 class="modal__header-bar">{% trans "Approve Contract" %}</h4> + <h4 class="modal__project-header-bar">{% trans "Approve Contract" %}</h4> <p>{% trans "You confirm that the uploaded contract is acceptable for commencing the project." %}</p> <p>{% trans "This cannot be undone." %}</p> {% trans "Confirm" as confirm %} diff --git a/hypha/apply/projects/templates/application_projects/includes/invoices.html b/hypha/apply/projects/templates/application_projects/includes/invoices.html index e166addba..f3afdfcf2 100644 --- a/hypha/apply/projects/templates/application_projects/includes/invoices.html +++ b/hypha/apply/projects/templates/application_projects/includes/invoices.html @@ -42,8 +42,8 @@ {% can_delete invoice user as user_can_delete_request %} {% if user_can_delete_request %} - <a class="data-block__action-icon-link" href="{% url 'apply:projects:invoice-delete' pk=invoice.project.pk invoice_pk=invoice.pk %}"> - <svg class="icon icon--delete"><use xlink:href="#delete"></use></svg> + <a class="data-block__action-icon-link data-block__action-icon-link--remove" href="{% url 'apply:projects:invoice-delete' pk=invoice.project.pk invoice_pk=invoice.pk %}"> + <svg class="icon icon--delete" style="margin-left:0; margin-right:2px"><use xlink:href="#delete"></use></svg> {% trans "Delete" %} </a> {% endif %} diff --git a/hypha/apply/projects/templates/application_projects/includes/report_frequency_config.html b/hypha/apply/projects/templates/application_projects/includes/report_frequency_config.html index fa7c1bc6b..f81ad7734 100644 --- a/hypha/apply/projects/templates/application_projects/includes/report_frequency_config.html +++ b/hypha/apply/projects/templates/application_projects/includes/report_frequency_config.html @@ -2,7 +2,7 @@ <div class="modal" id="change-frequency"> {{ report_data|json_script:"reportData" }} - <h4 class="modal__header-bar">{% trans "Change reporting frequency" %}</h4> + <h4 class="modal__project-header-bar">{% trans "Change reporting frequency" %}</h4> <div class="form__info-box"> <p> {% if config.disable_reporting %} 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 7f9d8ff77..4f293e594 100644 --- a/hypha/apply/projects/templates/application_projects/includes/report_line.html +++ b/hypha/apply/projects/templates/application_projects/includes/report_line.html @@ -28,7 +28,7 @@ <!-- Skip report confirmation modal --> <div class="modal" id="skip-report-{{report.id}}"> - <h4 class="modal__header-bar modal__header-bar--no-bottom-space">{% trans "Skip report" %}</h4> + <h4 class="modal__project-header-bar modal__project-header-bar--no-bottom-space">{% trans "Skip report" %}</h4> <div class="modal__copy"> <p>{% trans "You're skipping the report for" %} <b>{{report.start_date}}</b> – <b>{{report.end_date}}</b></p> <p>{% trans "This will result in a gap in reporting for the project. You can undo this at any time." %}</p> diff --git a/hypha/apply/projects/templates/application_projects/includes/supporting_documents.html b/hypha/apply/projects/templates/application_projects/includes/supporting_documents.html index 49190e696..e756f15b9 100644 --- a/hypha/apply/projects/templates/application_projects/includes/supporting_documents.html +++ b/hypha/apply/projects/templates/application_projects/includes/supporting_documents.html @@ -55,10 +55,6 @@ <svg class="icon icon--project-eye"><use xlink:href="#eye"></use></svg> {% trans "View" %} </a> - <a class="docs-block__icon-link" href="{% url "apply:submissions:download" pk=project.submission.pk %}"> - {% trans "Download" %} - <svg class="icon icon--caret-down"><use xlink:href="#caret-down"></use></svg> - </a> {% endif %} </div> </li> @@ -116,7 +112,7 @@ </div> {% has_project_sow_form object as project_sow %} {% if project_sow and object.user_has_updated_details and not user.is_applicant %} - <ul class="docs-block__document-list"> + <ul class="docs-block__document-list" style="padding-left:2.25rem;"> <li class="docs-block__document"> <div class="docs-block__document-inner"> <p class="docs-block__document-info">{% trans "Scope Of Work (SOW)" %}</p> @@ -126,16 +122,13 @@ <svg class="icon icon--project-eye"><use xlink:href="#eye"></use></svg> {% trans "View" %} </a> - <a class="docs-block__icon-link" href="{% url 'apply:projects:download-sow' pk=project.pk export_type='pdf' %}"> - {% trans "Download" %} - <svg class="icon icon--caret-down"><use xlink:href="#caret-down"></use></svg> - </a> </div> </li> </ul> {% endif %} </li> + {% if supporting_documents_configured %} <li class="docs-block__row"> <div class="docs-block__row-inner"> <svg class="icon docs-block__icon{% if not remaining_document_categories %} is-complete{% endif %}"> @@ -145,25 +138,14 @@ </div> {% if user.is_apply_staff %} <div class="docs-block__row-inner"> - {% if select_document_form.should_show %} - <a - data-fancybox - data-src="#copy-supporting-doc" - class="docs-block__link" - href="#"> - {% trans "Choose file" %} - </a> - {% else %} - <span class="docs-block__link is-disabled" data-tooltip="No files on submission">{% trans "Choose file" %}</span> - {% endif %} - <a data-fancybox data-src="#upload-supporting-doc" class="docs-block__icon-link" href="#"> - <svg class="icon icon--arrow-up"><use xlink:href="#arrow-up"></use></svg> + <a data-fancybox data-src="#upload-supporting-doc" class="docs-block__icon-link" style="margin-right:0;" href="#"> + <svg class="icon icon--arrow-up-short-bar"><use xlink:href="#arrow-up-short-bar"></use></svg> {% trans "Upload new" %} </a> </div> {% endif %} {% if remaining_document_categories %} - <ul class="docs-block__document-list"> + <ul class="docs-block__document-list" style="padding-left:2.25rem;"> <li class="docs-block__document"> <div class="docs-block__document-inner"> <p> @@ -180,23 +162,26 @@ {% endif %} {% if object.packet_files.exists %} - <ul class="docs-block__document-list"> + <ul class="docs-block__document-list" style="padding-left:2.25rem;"> {% for document in object.packet_files.all %} <li class="docs-block__document"> <div class="docs-block__document-inner"> <p class="docs-block__document-info">{{ document.category.name }}</p> <p class="docs-block__document-info"><b>{{ document.title }}</b> - {{ document.created_at }}</p> </div> - <div class="docs-block__document-inner"> - <a class="docs-block__document-link" href="{% url 'apply:projects:document' pk=object.pk file_pk=document.pk %}" target="_blank"> - {% trans "Download" %} + <div class="docs-block__row-inner"> + <a class="docs-block__icon-link" href="{% url 'apply:projects:document' pk=object.pk file_pk=document.pk %}" target="_blank"> + <svg class="icon icon--project-eye"><use xlink:href="#eye"></use></svg> + {% trans "View" %} </a> - {% if user.is_apply_staff %} - <form method="POST" id="{{ remove_document_form.name }}" class="docs-block__document-form"> + {% user_can_remove_supporting_documents object user as can_remove_supporting_doc %} + {% if can_remove_supporting_doc %} + <form method="POST" id="{{ remove_document_form.name }}" class="docs-block__icon-link"> + <svg class="icon icon--delete" style="margin-left:0; margin-right:2px"><use xlink:href="#delete"></use></svg> {% csrf_token %} {{ document.get_remove_form }} <input - class="button button--link" + class="button button--link button--remove" id="{{ remove_document_form.name }}-submit" name="{{ form_prefix }}{{ remove_document_form.name }}" type="submit" @@ -211,19 +196,20 @@ {% endif %} </li> + {% endif %} </ul> </div> {% if user.is_apply_staff %} <div class="modal" id="copy-supporting-doc"> - <h4 class="modal__header-bar">{% trans "Select a document" %}</h4> + <h4 class="modal__project-header-bar">{% trans "Select a document" %}</h4> {% url 'apply:projects:copy-documents' pk=object.pk as select_document_url %} {% trans "Copy" as copy %} {% include 'funds/includes/delegated_form_base.html' with form=select_document_form value=copy action=select_document_url %} </div> <div class="modal" id="upload-supporting-doc"> - <h4 class="modal__header-bar">{% trans "Upload a new document" %}</h4> + <h4 class="modal__project-header-bar">{% trans "Upload supporting documents" %}</h4> <p></p> {% trans "Submit" as submit %} {% include 'funds/includes/delegated_form_base.html' with form=document_form value=submit %} @@ -232,7 +218,7 @@ {% if can_send_to_approve %} <div class="modal" id="send-for-approval"> - <h4 class="modal__header-bar">{% trans "Request Approval" %}</h4> + <h4 class="modal__project-header-bar">{% trans "Submit for Approval" %}</h4> {% if remaining_document_categories %} <h5>{% trans "Are you sure you're ready to submit?" %}</h5> @@ -246,11 +232,12 @@ </ul> {% trans "Submit anyway" as submit %} {% else %} - {% trans "Request" as submit %} + {% trans "Submit" as submit %} {% endif %} {% if project_settings.paf_reviewers_roles.all %} <p> <strong> {% trans "Please select approvers for PAF in " %} {% if project_settings.paf_approval_sequential %} {% trans "sequential order" %} {% else %}{% trans "parallel order" %}{% endif %}</strong></p> <p>{% trans "(please note that in "%}{% if project_settings.paf_approval_sequential %}{%trans "sequential order, approvers will approve PAF one after the other)"%}{% else %}{% trans "parallel order, approvers can approve PAF anytime)" %}{% endif %}</p> + <br> {% include 'funds/includes/delegated_form_base.html' with form=request_approval_form value=submit %} {% else %} <p>{% trans "No PAF Reviewer Roles created yet, please create these in " %} @@ -262,12 +249,13 @@ {% if can_update_paf_approvers %} <div class="modal" id="update-paf-approvers"> - <h4 class="modal__header-bar">{% trans "Update Approvers" %}</h4> + <h4 class="modal__project-header-bar">{% trans "View/Update Approvers" %}</h4> {% trans "Submit" as submit %} {% if project_settings.paf_reviewers_roles.all %} - <p> {% trans "Are you sure you want to update the approvers? The approvers will be notified via email." %} {% if project_settings.paf_approval_sequential %} {% trans "(Sequentially)" %} {% else %}{% trans "(Parallely)" %}{% endif %}</p> - {% include 'funds/includes/delegated_form_base.html' with form=update_approvers_form value=submit %} + <p> {% trans "Are you sure you want to update the approvers?" %} {% if project_settings.paf_approval_sequential %} {% trans "The uppermost active approver will be notified via email." %} {% else %}{% trans "All approvers will be notified via email." %}{% endif %}</p> + <br> + {% include 'funds/includes/delegated_form_base.html' with form=update_approvers_form value=submit %} {% else %} <p>{% trans "No PAF Reviewer Roles created yet, please create these in " %} <a href="{% project_settings_url project_settings %}" target="_blank">{% trans " project settings" %}</a> @@ -278,7 +266,7 @@ {% if can_update_paf_status %} <div class="modal" id="update-paf-status"> - <h4 class="modal__header-bar">{% trans "Update PAF Status" %}</h4> + <h4 class="modal__project-header-bar">{% trans "Update PAF Status" %}</h4> <p>{% trans "Project's current status" %}: {{ object.get_status_display }}</p> {% trans "Update Status" as update %} {% include 'funds/includes/delegated_form_base.html' with form=change_paf_status value=update %} diff --git a/hypha/apply/projects/templates/application_projects/invoice_admin_detail.html b/hypha/apply/projects/templates/application_projects/invoice_admin_detail.html index 9f775a8b8..bd6f6876c 100644 --- a/hypha/apply/projects/templates/application_projects/invoice_admin_detail.html +++ b/hypha/apply/projects/templates/application_projects/invoice_admin_detail.html @@ -23,7 +23,7 @@ </a> {% if user_can_change_status %} <div class="modal" id="change-status"> - <h4 class="modal__header-bar">{% trans "Update Invoice status" %}</h4> + <h4 class="modal__project-header-bar">{% trans "Update Invoice status" %}</h4> <p>{% trans "Current status" %}: {{ object.get_status_display }}</p> {% trans "Update Status" as update %} {% include 'funds/includes/delegated_form_base.html' with form=change_invoice_status value=update %} diff --git a/hypha/apply/projects/templates/application_projects/invoice_detail.html b/hypha/apply/projects/templates/application_projects/invoice_detail.html index 1ce61007d..e75e68945 100644 --- a/hypha/apply/projects/templates/application_projects/invoice_detail.html +++ b/hypha/apply/projects/templates/application_projects/invoice_detail.html @@ -17,7 +17,10 @@ <div class="wrapper--sidebar--inner"> <div class="card card--solid"> <p class="card__text"><b>{% trans "Status" %}:</b> {{ object.get_status_display }}</p> + {% is_vendor_setup request as show_vendor_information %} + {% if show_vendor_information %} <p class="card__text"><b>{% trans "Vendor" %}:</b> {{ object.project.vendor.name }}</p> + {% endif %} <p class="card__text"><b>{% trans "Invoice Number" %}:</b> {{ object.vendor_document_number }}</p> </div> @@ -42,6 +45,7 @@ <h5>{% trans "Actions to take" %}</h5> {% block actions %} {% can_edit object user as user_can_edit_request %} + {% if user.is_apply_staff or user.is_applicant %} <a {% if not user_can_edit_request %} data-tooltip="{% trans "Only editable when 'Submitted' or you have been requested to make changes" %}" @@ -55,6 +59,7 @@ > {% trans "Edit" %} </a> + {% endif %} {% can_delete object user as user_can_delete_request %} {% if user_can_delete_request %} <a diff --git a/hypha/apply/projects/templates/application_projects/project_admin_detail.html b/hypha/apply/projects/templates/application_projects/project_admin_detail.html index 907b4341f..56eaa2d97 100644 --- a/hypha/apply/projects/templates/application_projects/project_admin_detail.html +++ b/hypha/apply/projects/templates/application_projects/project_admin_detail.html @@ -18,7 +18,7 @@ <a data-fancybox data-src="#project-status" class="button button--white button--full-width button--bottom-space" href="#">{% trans "Update Project Status" %}</a> <div class="modal" id="project-status"> - <h4 class="modal__header-bar">{% trans "Update Project Status" %}</h4> + <h4 class="modal__project-header-bar">{% trans "Update Project Status" %}</h4> {% trans "Update" as update %} {% include 'funds/includes/delegated_form_base.html' with form=change_project_status value=update %} </div> diff --git a/hypha/apply/projects/templates/application_projects/project_approval_detail.html b/hypha/apply/projects/templates/application_projects/project_approval_detail.html index 73a4f1c61..9e03f0a26 100644 --- a/hypha/apply/projects/templates/application_projects/project_approval_detail.html +++ b/hypha/apply/projects/templates/application_projects/project_approval_detail.html @@ -168,7 +168,7 @@ </div> <a data-fancybox data-src="#change-status" class="button button--primary button--full-width {% if user_can_approve %} is-disabled {% endif %}" href="#">{% trans "Update Status" %}</a> <div class="modal" id="change-status"> - <h4 class="modal__header-bar">{% trans "Update PAF Status" %}</h4> + <h4 class="modal__project-header-bar">{% trans "Update status" %}</h4> <p>{% trans "Project's current status" %}: {{ object.get_status_display }}</p> {% trans "Update Status" as update %} {% include 'funds/includes/delegated_form_base.html' with form=change_paf_status value=update %} diff --git a/hypha/apply/projects/templates/application_projects/project_approval_form.html b/hypha/apply/projects/templates/application_projects/project_approval_form.html index 6799ca239..8225020a7 100644 --- a/hypha/apply/projects/templates/application_projects/project_approval_form.html +++ b/hypha/apply/projects/templates/application_projects/project_approval_form.html @@ -77,7 +77,7 @@ <div class="wrapper--sidebar--inner"> <p> {% trans "Approval form not configured. Please add an approval form in the" %} - <a href="{% url 'funds_fundtype_modeladmin_edit' object.submission.page.id %}" target="_blank">{% trans "fund settings" %}</a>. + <a href="{% url 'wagtailadmin_pages:edit' object.submission.page.id %}" target="_blank">{% trans "fund settings" %}</a>. </p> </div> </div> diff --git a/hypha/apply/projects/templates/application_projects/project_detail.html b/hypha/apply/projects/templates/application_projects/project_detail.html index 15d81d43c..486890be9 100644 --- a/hypha/apply/projects/templates/application_projects/project_detail.html +++ b/hypha/apply/projects/templates/application_projects/project_detail.html @@ -46,7 +46,7 @@ <svg class="icon icon--pen"><use xlink:href="#pen"></use></svg> </a> <div class="modal" id="assign-lead"> - <h4 class="modal__header-bar">{% trans "Assign Lead" %}</h4> + <h4 class="modal__project-header-bar">{% trans "Assign Lead" %}</h4> {% trans "Update" as update %} {% include 'funds/includes/delegated_form_base.html' with form=lead_form value=update %} </div> @@ -185,7 +185,7 @@ <h5>{% trans "PAF Approvals" %}</h5> {% for paf_approval in object.paf_approvals.all %} {% if paf_approval.approved %} - <p class="sidebar__paf-approvals--approved">{% trans "Approved by " %}{{ paf_approval.user }}</p> + <p class="sidebar__paf-approvals--approved">{% trans "Approved by " %}{{ paf_approval.user }} {% if paf_approval.approved_at %}(<i>{{ paf_approval.approved_at|date }}</i>){% endif %}</p> {% else %} <p class="sidebar__paf-approvals--pending">{% trans "Pending approval from " %}{{ paf_approval.user }}</p> {% endif %} diff --git a/hypha/apply/projects/templates/application_projects/project_sow_detail.html b/hypha/apply/projects/templates/application_projects/project_sow_detail.html index 571311555..6e47844ac 100644 --- a/hypha/apply/projects/templates/application_projects/project_sow_detail.html +++ b/hypha/apply/projects/templates/application_projects/project_sow_detail.html @@ -42,7 +42,7 @@ <div class="wrapper wrapper--large wrapper--tabs"> <div class="wrapper wrapper--sidebar"> <article class="wrapper--sidebar--inner simplified__wrapper"> - <h3>{% trans "Project Scope of Work(SOW)" %}</h3> + <h3>{% trans "Project scope of work(SOW)" %}</h3> <div class="card card--solid"> {% if object.sow.output_answers %} <div class="simplified__rich-text"> diff --git a/hypha/apply/projects/templates/application_projects/report_form.html b/hypha/apply/projects/templates/application_projects/report_form.html index b6a3cbc54..1cfc94a21 100644 --- a/hypha/apply/projects/templates/application_projects/report_form.html +++ b/hypha/apply/projects/templates/application_projects/report_form.html @@ -47,7 +47,7 @@ <!-- Save report modal --> <div class="modal" id="save-report"> - <h4 class="modal__header-bar">{% trans "Save report" %}</h4> + <h4 class="modal__project-header-bar">{% trans "Save report" %}</h4> <div class="modal__copy"> <p>{% trans "Saving a draft means this report will be visible to you and staff from your project page." %}</p> </div> @@ -59,7 +59,7 @@ <!-- Submit report modal --> <div class="modal" id="submit-report"> - <h4 class="modal__header-bar">{% trans "Submit report" %}</h4> + <h4 class="modal__project-header-bar">{% trans "Submit report" %}</h4> <p>{% trans "Are you sure you want to submit your report?" %}</p> <div class="modal__buttons"> <button data-fancybox-close class="button button--submit button--white">{% trans "Cancel" %}</button> diff --git a/hypha/apply/projects/templatetags/contract_tools.py b/hypha/apply/projects/templatetags/contract_tools.py index 0407104b5..d3cc8a556 100644 --- a/hypha/apply/projects/templatetags/contract_tools.py +++ b/hypha/apply/projects/templatetags/contract_tools.py @@ -53,7 +53,7 @@ def user_can_upload_contract(project, user): def show_contract_upload_row(project, user): if project.status != CONTRACTING: return False - if (user.is_contracting or user == project.user) and not user.is_apply_staff: + if user.is_contracting or user == project.user or user.is_apply_staff: return True return False diff --git a/hypha/apply/projects/templatetags/invoice_tools.py b/hypha/apply/projects/templatetags/invoice_tools.py index 8465044cc..11552a1b8 100644 --- a/hypha/apply/projects/templatetags/invoice_tools.py +++ b/hypha/apply/projects/templatetags/invoice_tools.py @@ -2,7 +2,12 @@ import decimal from django import template -from hypha.apply.projects.models.project import CLOSING, COMPLETE, IN_PROGRESS +from hypha.apply.projects.models.project import ( + CLOSING, + COMPLETE, + IN_PROGRESS, + ProjectSettings, +) register = template.Library() @@ -55,3 +60,9 @@ def user_can_add_invoices(project, user): if project.status == IN_PROGRESS and (user.is_apply_staff or user == project.user): return True return False + + +@register.simple_tag +def is_vendor_setup(request): + project_settings = ProjectSettings.for_request(request) + return project_settings.vendor_setup_required diff --git a/hypha/apply/projects/templatetags/project_tags.py b/hypha/apply/projects/templatetags/project_tags.py index 3e9e8f219..40666c296 100644 --- a/hypha/apply/projects/templatetags/project_tags.py +++ b/hypha/apply/projects/templatetags/project_tags.py @@ -43,7 +43,7 @@ def user_next_step_on_project(project, user): if not contract.signed_by_applicant: if user.is_applicant: return "Awaiting contract documents to be submitted by applicant." - return "Awaiting counter-signed contract from Applicant" + return "Awaiting countersigned contract from Applicant" elif not project.submitted_contract_documents: return "Awaiting contract documents submission from Applicant" else: @@ -51,8 +51,10 @@ def user_next_step_on_project(project, user): return "Review the contract for all relevant details and approve." return "Awaiting contract approval from Staff" elif project.status == IN_PROGRESS: - if user.is_applicant or user.is_apply_staff: + if user.is_applicant: return "Add invoices" + elif user.is_apply_staff: + return "Review invoice and take action" return False @@ -138,3 +140,10 @@ def allow_collapsible_header(project, header_type): if header_type == 'contracting_documents' and project.status not in [COMMITTED, WAITING_FOR_APPROVAL, CONTRACTING]: return True return False + + +@register.simple_tag +def user_can_remove_supporting_documents(project, user): + if user.is_apply_staff and project.status == COMMITTED: + return True + return False diff --git a/hypha/apply/projects/views/project.py b/hypha/apply/projects/views/project.py index 81ac9693e..9fa762881 100644 --- a/hypha/apply/projects/views/project.py +++ b/hypha/apply/projects/views/project.py @@ -77,7 +77,9 @@ from ..models.project import ( REQUEST_CHANGE, WAITING_FOR_APPROVAL, Contract, + ContractDocumentCategory, ContractPacketFile, + DocumentCategory, PacketFile, PAFApprovals, Project, @@ -379,7 +381,7 @@ class UploadContractView(DelegatedViewMixin, CreateView): if self.request.user == project.user: form.instance.signed_by_applicant = True form.instance.uploaded_by_applicant_at = timezone.now() - messages.success(self.request, _("CounterSigned contract uploaded"), extra_tags=PROJECT_ACTION_MESSAGE_TAG) + messages.success(self.request, _("Countersigned contract uploaded"), extra_tags=PROJECT_ACTION_MESSAGE_TAG) elif self.request.user.is_contracting: form.instance.uploaded_by_contractor_at = timezone.now() messages.success(self.request, _("Signed contract uploaded"), extra_tags=PROJECT_ACTION_MESSAGE_TAG) @@ -455,7 +457,7 @@ class UploadContractDocumentView(DelegatedViewMixin, CreateView): # PROJECT VIEW -@method_decorator(staff_or_finance_or_contracting_required, name='dispatch') +@method_decorator(login_required, name='dispatch') class ChangePAFStatusView(DelegatedViewMixin, UpdateView): form_class = ChangePAFStatusForm context_name = 'change_paf_status' @@ -500,7 +502,8 @@ class ChangePAFStatusView(DelegatedViewMixin, UpdateView): extra_tags=PROJECT_ACTION_MESSAGE_TAG) elif paf_status == APPROVE: paf_approval.approved = True - paf_approval.save(update_fields=['approved']) + paf_approval.approved_at = timezone.now() + paf_approval.save(update_fields=['approved', 'approved_at']) project_settings = ProjectSettings.for_request(self.request) if project_settings.paf_approval_sequential: # notify next approver @@ -639,6 +642,8 @@ class BaseProjectDetailView(ReportingMixin, DetailView): context = super().get_context_data(**kwargs) context['statuses'] = PROJECT_STATUS_CHOICES context['current_status_index'] = [status for status, _ in PROJECT_STATUS_CHOICES].index(self.object.status) + context['supporting_documents_configured'] = True if DocumentCategory.objects.count() else False + context['contracting_documents_configured'] = True if ContractDocumentCategory.objects.count() else False return context @@ -671,6 +676,7 @@ class AdminProjectDetailView( context['project_settings'] = project_settings context['paf_approvals'] = PAFApprovals.objects.filter(project=self.object) context['remaining_document_categories'] = list(self.object.get_missing_document_categories()) + context['remaining_contract_document_categories'] = list(self.object.get_missing_contract_document_categories()) if self.object.is_in_progress and not self.object.report_config.disable_reporting: # Current due report can be none for ONE_TIME, diff --git a/hypha/static_src/src/sass/apply/components/_button.scss b/hypha/static_src/src/sass/apply/components/_button.scss index d9453eabe..391a3b559 100644 --- a/hypha/static_src/src/sass/apply/components/_button.scss +++ b/hypha/static_src/src/sass/apply/components/_button.scss @@ -354,6 +354,10 @@ color: $color--primary; } + &--remove { + color: $color--tomato; + } + &--tooltip-disabled { background-color: $color--button-disabled; diff --git a/hypha/static_src/src/sass/apply/components/_data-block.scss b/hypha/static_src/src/sass/apply/components/_data-block.scss index 822cfe774..c24c2a761 100644 --- a/hypha/static_src/src/sass/apply/components/_data-block.scss +++ b/hypha/static_src/src/sass/apply/components/_data-block.scss @@ -181,13 +181,16 @@ display: flex; align-items: center; margin-right: 1rem; - text-decoration: underline; color: $color--primary; word-break: normal; &:last-child { margin: 0; } + + &--remove { + color: $color--tomato; + } } &__list-item { diff --git a/hypha/static_src/src/sass/apply/components/_docs-block.scss b/hypha/static_src/src/sass/apply/components/_docs-block.scss index 143581acb..2ac66caff 100644 --- a/hypha/static_src/src/sass/apply/components/_docs-block.scss +++ b/hypha/static_src/src/sass/apply/components/_docs-block.scss @@ -136,12 +136,8 @@ &__document-list { width: 100%; - margin-top: 1.5rem; + margin-top: 1rem; padding-left: 0; - - @include media-query(tablet-landscape) { - padding-left: 3rem; - } } &__document { @@ -149,8 +145,6 @@ align-items: center; justify-content: space-between; padding-bottom: 1rem; - margin: 1rem 0; - border-bottom: 1px solid $color--light-mid-grey; flex-wrap: wrap; &:last-child { diff --git a/hypha/static_src/src/sass/apply/components/_icon.scss b/hypha/static_src/src/sass/apply/components/_icon.scss index 5b217c820..512e051c2 100644 --- a/hypha/static_src/src/sass/apply/components/_icon.scss +++ b/hypha/static_src/src/sass/apply/components/_icon.scss @@ -141,9 +141,21 @@ fill: $color--light-blue; } + &--arrow-up-short-bar { + position: relative; + align-self: center; + height: 1.4em; + margin-right: 2px; + fill: $color--light-blue; + + &--contract-upload { + stroke: $color--white; + } + } + &--project-pen { width: 12px; - margin-right: 5px; + margin-right: 3px; fill: $color--light-blue; } @@ -196,6 +208,7 @@ width: 18px; height: 18px; cursor: pointer; + margin-right: 3px; vertical-align: middle; } } diff --git a/hypha/static_src/src/sass/apply/components/_modal.scss b/hypha/static_src/src/sass/apply/components/_modal.scss index 1ffd972e0..8eb2bac07 100644 --- a/hypha/static_src/src/sass/apply/components/_modal.scss +++ b/hypha/static_src/src/sass/apply/components/_modal.scss @@ -21,6 +21,18 @@ } } + &__project-header-bar { + color: $color--white; + background-color: $color--dark-blue; + margin: -24px -24px 20px; + padding: 15px 24px; + text-align: left; + + &--no-bottom-space { + margin-bottom: 0; + } + } + &__list { max-height: 200px; overflow: scroll; diff --git a/hypha/templates/includes/sprites.html b/hypha/templates/includes/sprites.html index 71919af2a..dca72aaab 100644 --- a/hypha/templates/includes/sprites.html +++ b/hypha/templates/includes/sprites.html @@ -236,6 +236,13 @@ <path fill-rule="evenodd" d="M8 10a.5.5 0 0 0 .5-.5V3.707l2.146 2.147a.5.5 0 0 0 .708-.708l-3-3a.5.5 0 0 0-.708 0l-3 3a.5.5 0 1 0 .708.708L7.5 3.707V9.5a.5.5 0 0 0 .5.5zm-7 2.5a.5.5 0 0 1 .5-.5h13a.5.5 0 0 1 0 1h-13a.5.5 0 0 1-.5-.5z"/> </symbol> + <svg id="arrow-up-short-bar" viewBox="0 0 16 17" fill="none"> + <path d="M8 3L8 13" stroke-width="2"/> + <path d="M3 15H13" stroke-width="2"/> + <path d="M1 8L8 2L15 8" stroke-width="2"/> + </svg> + + <symbol id="wifi" viewBox="0 0 69 42"> <g stroke-width="6" fill="none" fill-rule="evenodd"> -- GitLab