diff --git a/hypha/apply/activity/adapters/emails.py b/hypha/apply/activity/adapters/emails.py index 2ccbfe5c8a958cb903bb3b75577f7b7d32a2c514..6741107a2fe7a5636e0ceb6f1f5c0856a30cae74 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 0000000000000000000000000000000000000000..64bf7ae516b727557788ebb7137fbfa257b6cbbe --- /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 9afdcf593b34b605443c76dd2d017612a85a9f1a..3e9b0ba55122c8714adea3c31eb76377e7e75da1 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 0000000000000000000000000000000000000000..c5378ff36e91f7836f93d04337aae2ab3b862508 --- /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 d04d2cf93dd01760159d361826d01d40150cfad7..b95088d68dd29d9118f301aa8d436480d952c046 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 0000000000000000000000000000000000000000..e6a6d389813b2b32de9fd736d0bd0f1b298d41cc --- /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 0000000000000000000000000000000000000000..7de4db38924b5fd4e2d86a12d7dd709863e34a35 --- /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 b58709084fd0b0a319177f039bbc0bfbf63ce940..8b232bbaad81349e3a457d1cfdf9424899f80d92 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 6f97e2af93a315f4845f048f9ec3f57972a7fad6..400cb97815b4b651397a846e590468f42f216d44 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 5cac56f9db55092673502170e9666133b1d96986..66330783ac11d22bcae4e5c24a917de40d86f95c 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 e166addba45f3a3ded1dc795bba23273aa85be7f..f3afdfcf265dd1e618544d1d6278d8002bc54cce 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 fa7c1bc6bd225c5a793a487eb6233590de8b8f8e..f81ad773480e09e64a36e1b88f7f1547190e29d4 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 7f9d8ff77e12ba4efad2f3f1ab6913f565384698..4f293e594a36ac155ae9f02925d9939810f63929 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 49190e696acd76ecb745a3c64e26b5c0c0d1fa72..e756f15b9a5b4e0970ef0d34b7ae7042c45c1f84 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 9f775a8b8a5ac86c1ece6f147d1f5309779ace26..bd6f6876c41c10f98bc4e9ec51a44164abcdddcc 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 1ce61007dc523be8f124e5e01c2f312dc499499d..e75e68945cb87388a3cce535501d31e254223ac0 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 907b4341f4b881f8012a7718aced0447f9b6038d..56eaa2d97707b6b8a376dfe00ea1353a86ee58ea 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 73a4f1c61ac0c19aa6bc4c6e0ae2566834bd5c82..9e03f0a26b27535fe6cec8bdcb124922709d6d9a 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 6799ca239d153423e186ed72f183e48e1971ada3..8225020a7a30d021d7f2173d90a83cc721736560 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 15d81d43c2cb742f28a237c7a5da6cb3f03d4d00..486890be9843ff3f0204e2f342c591f53acd5832 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 5713115552e6ad0ab2ad469ad23fdc28a1a2ff14..6e47844ac0c3216c9f72116bbbbb5917f0221078 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 b6a3cbc54d132bfa59fe1ca0e651a2c5114cf0d8..1cfc94a219b1242b0f7617c3d0f66a77595645f8 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 0407104b503a550027dfdde8de93c5bef2c7badd..d3cc8a556ca087f5f6fb2302d0884942cd3c88c7 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 8465044cc6f19cef8b830437b5175fbbbfd72212..11552a1b8bc22dc8705138b1d1094adbfc2e9fe9 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 3e9e8f219edde4b2d8c926b7863178ad750771c0..40666c296bcdef6513b7994907888748b104fd0a 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 81ac9693e403f8131783e1d06f21ba394c92390d..9fa762881e51d73a2e714ca11198adbbc81bcb4b 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 d9453eabea8bc0c8d221bd73f4fb9ed1c1884dce..391a3b55983207a4fc41fca2b73c819f8e0ac3a1 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 822cfe77454e3b9bd9603578d5f0c33c607df39b..c24c2a761e36ad8561cd585cac1c281b9147619c 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 143581acbb7aec42e6dd4f6be654333e581b6520..2ac66caffbe18f4cf7061017726baeb007986b7a 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 5b217c820584c8a89f4de5bc1062f3f63e70ef55..512e051c2d1cadf0dd21e9d0369a60c57ddf9c4f 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 1ffd972e0f598834a06c51834066ad04f290c034..8eb2bac07bfe15c3604132297f6045db77627f78 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 71919af2a85b3fdbc5b4f15695d9aef805b66239..dca72aaabd29b7556af6818393856a17ecd1b5fa 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">