diff --git a/hypha/apply/activity/adapters/base.py b/hypha/apply/activity/adapters/base.py index 6889e34272f7e9e928dcca2623f8d84c91504c68..ef76c1403e326b44f41d0ec6dfcd1ab7e1347121 100644 --- a/hypha/apply/activity/adapters/base.py +++ b/hypha/apply/activity/adapters/base.py @@ -22,6 +22,7 @@ neat_related = { MESSAGES.PROJECT_TRANSITION: "old_stage", MESSAGES.APPROVE_PAF: "paf_approvals", # expect a list MESSAGES.UPDATE_PROJECT_LEAD: "old_lead", + MESSAGES.UPDATE_PROJECT_TITLE: "old_title", MESSAGES.APPROVE_CONTRACT: "contract", MESSAGES.UPLOAD_CONTRACT: "contract", MESSAGES.CREATE_INVOICE: "create_invoice", diff --git a/hypha/apply/activity/adapters/slack.py b/hypha/apply/activity/adapters/slack.py index 74d0daaf2a2309b8f002c58cd8d47cd4a49137d0..2f5b7446e5dd39fe45188687c6e4f06b88405c52 100644 --- a/hypha/apply/activity/adapters/slack.py +++ b/hypha/apply/activity/adapters/slack.py @@ -83,6 +83,9 @@ class SlackAdapter(AdapterBase): MESSAGES.UPDATE_PROJECT_LEAD: _( "The lead of project <{link}|{source.title}> has been updated from {old_lead} to {source.lead} by {user}" ), + MESSAGES.UPDATE_PROJECT_TITLE: _( + "The project title has been updated from <{link}|{old_title}> to <{link}|{source.title}> by {user}" + ), MESSAGES.EDIT_REVIEW: _( "{user} has edited {review.author} review for <{link}|{source.title}>" ), diff --git a/hypha/apply/activity/migrations/0081_alter_event_type.py b/hypha/apply/activity/migrations/0081_alter_event_type.py new file mode 100644 index 0000000000000000000000000000000000000000..1d598007c7c977fa32a71e2820a302450c8fc42e --- /dev/null +++ b/hypha/apply/activity/migrations/0081_alter_event_type.py @@ -0,0 +1,85 @@ +# Generated by Django 4.2.11 on 2024-05-20 07:15 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + dependencies = [ + ("activity", "0080_alter_event_type"), + ] + + operations = [ + migrations.AlterField( + model_name="event", + name="type", + field=models.CharField( + choices=[ + ("UPDATE_LEAD", "updated lead"), + ("BATCH_UPDATE_LEAD", "batch updated lead"), + ("EDIT_SUBMISSION", "edited submission"), + ("APPLICANT_EDIT", "edited applicant"), + ("NEW_SUBMISSION", "submitted new submission"), + ("DRAFT_SUBMISSION", "submitted new draft submission"), + ("SCREENING", "screened"), + ("TRANSITION", "transitioned"), + ("BATCH_TRANSITION", "batch transitioned"), + ("DETERMINATION_OUTCOME", "sent determination outcome"), + ("BATCH_DETERMINATION_OUTCOME", "sent batch determination outcome"), + ("INVITED_TO_PROPOSAL", "invited to proposal"), + ("REVIEWERS_UPDATED", "updated reviewers"), + ("BATCH_REVIEWERS_UPDATED", "batch updated reviewers"), + ("PARTNERS_UPDATED", "updated partners"), + ("PARTNERS_UPDATED_PARTNER", "partners updated partner"), + ("READY_FOR_REVIEW", "marked ready for review"), + ("BATCH_READY_FOR_REVIEW", "marked batch ready for review"), + ("NEW_REVIEW", "added new review"), + ("COMMENT", "added comment"), + ("PROPOSAL_SUBMITTED", "submitted proposal"), + ("OPENED_SEALED", "opened sealed submission"), + ("REVIEW_OPINION", "reviewed opinion"), + ("DELETE_SUBMISSION", "deleted submission"), + ("DELETE_REVIEW", "deleted review"), + ("DELETE_REVIEW_OPINION", "deleted review opinion"), + ("CREATED_PROJECT", "created project"), + ("UPDATED_VENDOR", "updated contracting information"), + ("UPDATE_PROJECT_LEAD", "updated project lead"), + ("UPDATE_PROJECT_TITLE", "updated project title"), + ("EDIT_REVIEW", "edited review"), + ("SEND_FOR_APPROVAL", "sent for approval"), + ("APPROVE_PROJECT", "approved project"), + ("ASSIGN_PAF_APPROVER", "assign paf approver"), + ("APPROVE_PAF", "approved paf"), + ("PROJECT_TRANSITION", "transitioned project"), + ("REQUEST_PROJECT_CHANGE", "requested project change"), + ("SUBMIT_CONTRACT_DOCUMENTS", "submitted contract documents"), + ("UPLOAD_DOCUMENT", "uploaded document to project"), + ("REMOVE_DOCUMENT", "removed document from project"), + ("UPLOAD_CONTRACT", "uploaded contract to project"), + ("APPROVE_CONTRACT", "approved contract"), + ("CREATE_INVOICE", "created invoice for project"), + ("UPDATE_INVOICE_STATUS", "updated invoice status"), + ("APPROVE_INVOICE", "approve invoice"), + ("DELETE_INVOICE", "deleted invoice"), + ("SENT_TO_COMPLIANCE", "sent project to compliance"), + ("UPDATE_INVOICE", "updated invoice"), + ("SUBMIT_REPORT", "submitted report"), + ("SKIPPED_REPORT", "skipped report"), + ("REPORT_FREQUENCY_CHANGED", "changed report frequency"), + ("DISABLED_REPORTING", "disabled reporting"), + ("REPORT_NOTIFY", "notified report"), + ("CREATE_REMINDER", "created reminder"), + ("DELETE_REMINDER", "deleted reminder"), + ("REVIEW_REMINDER", "reminder to review"), + ("BATCH_DELETE_SUBMISSION", "batch deleted submissions"), + ("BATCH_ARCHIVE_SUBMISSION", "batch archive submissions"), + ("BATCH_INVOICE_STATUS_UPDATE", "batch update invoice status"), + ("STAFF_ACCOUNT_CREATED", "created new account"), + ("STAFF_ACCOUNT_EDITED", "edited account"), + ("ARCHIVE_SUBMISSION", "archived submission"), + ("UNARCHIVE_SUBMISSION", "unarchived submission"), + ], + max_length=50, + verbose_name="verb", + ), + ), + ] diff --git a/hypha/apply/activity/options.py b/hypha/apply/activity/options.py index 2675ec57c297bb21ab3a4d367d05a0225520e6ba..52ed937bca82239f8a7a1e0923db74a191056cf0 100644 --- a/hypha/apply/activity/options.py +++ b/hypha/apply/activity/options.py @@ -39,6 +39,7 @@ class MESSAGES(TextChoices): CREATED_PROJECT = "CREATED_PROJECT", _("created project") UPDATED_VENDOR = "UPDATED_VENDOR", _("updated contracting information") UPDATE_PROJECT_LEAD = "UPDATE_PROJECT_LEAD", _("updated project lead") + UPDATE_PROJECT_TITLE = "UPDATE_PROJECT_TITLE", _("updated project title") EDIT_REVIEW = "EDIT_REVIEW", _("edited review") SEND_FOR_APPROVAL = "SEND_FOR_APPROVAL", _("sent for approval") APPROVE_PROJECT = "APPROVE_PROJECT", _("approved project") diff --git a/hypha/apply/projects/forms/__init__.py b/hypha/apply/projects/forms/__init__.py index 3917813c4c54b8bdcfab2b006eec9db1976190a1..3a8ccfcb70b434f566488c1d3f1c6a8726ac2df9 100644 --- a/hypha/apply/projects/forms/__init__.py +++ b/hypha/apply/projects/forms/__init__.py @@ -21,6 +21,7 @@ from .project import ( StaffUploadContractForm, SubmitContractDocumentsForm, UpdateProjectLeadForm, + UpdateProjectTitleForm, UploadContractDocumentForm, UploadContractForm, UploadDocumentForm, @@ -36,6 +37,7 @@ from .vendor import ( ) __all__ = [ + "UpdateProjectTitleForm", "SelectDocumentForm", "SubmitContractDocumentsForm", "SkipPAFApprovalProcessForm", diff --git a/hypha/apply/projects/forms/project.py b/hypha/apply/projects/forms/project.py index b7923a8b1eae69e8fa3dbf3db19c2d20eeb51541..aa3a067ee8d7959ddf066d61976b795f905edda7 100644 --- a/hypha/apply/projects/forms/project.py +++ b/hypha/apply/projects/forms/project.py @@ -438,3 +438,12 @@ class UpdateProjectLeadForm(forms.ModelForm): .filter(qwargs) .distinct() ) + + +class UpdateProjectTitleForm(forms.ModelForm): + class Meta: + fields = ["title"] + model = Project + + def __init__(self, user=None, *args, **kwargs): + super().__init__(*args, **kwargs) diff --git a/hypha/apply/projects/templates/application_projects/project_detail.html b/hypha/apply/projects/templates/application_projects/project_detail.html index ec2ae135d00624cf2b4f0c44430baae2b524ec98..ade4c639ec666e10578018e79823ba27223a5b0b 100644 --- a/hypha/apply/projects/templates/application_projects/project_detail.html +++ b/hypha/apply/projects/templates/application_projects/project_detail.html @@ -17,7 +17,22 @@ {% endif %} <div class="admin-bar"> <div class="admin-bar__inner"> - <h1 class="mb-0 font-medium">{{ object.title }}</h1> + <h1 class="mb-0 font-medium">{{ object.title }} + {% if request.user.is_apply_staff %} + <a data-fancybox + data-src="#update-title" + class="link is-active link--transparent hover:opacity-70 transition-opacity" + href="#"> + {% heroicon_solid "pencil-square" class="inline ms-1 mt-2" aria_hidden=true %} + </a> + <div class="modal" id="update-title"> + <h4 class="modal__project-header-bar">{% trans "Update Title" %}</h4> + {% trans "Update" as update %} + {% include 'funds/includes/delegated_form_base.html' with form=title_form value=update %} + </div> + {% endif %} + </h1> + <div class="heading heading--meta text-sm mt-1 font-medium"> <span>{{ object.submission.page }}</span> diff --git a/hypha/apply/projects/views/project.py b/hypha/apply/projects/views/project.py index 30505e197b9e5bc43312dcd03e7d445baea06ca4..a7647c32217d2c1c0999c25fcb263f6c967880e4 100644 --- a/hypha/apply/projects/views/project.py +++ b/hypha/apply/projects/views/project.py @@ -84,6 +84,7 @@ from ..forms import ( SkipPAFApprovalProcessForm, SubmitContractDocumentsForm, UpdateProjectLeadForm, + UpdateProjectTitleForm, UploadContractDocumentForm, UploadContractForm, UploadDocumentForm, @@ -397,6 +398,35 @@ class UpdateLeadView(DelegatedViewMixin, UpdateView): return response +@method_decorator(staff_required, name="dispatch") +class UpdateProjectTitleView(DelegatedViewMixin, UpdateView): + model = Project + form_class = UpdateProjectTitleForm + context_name = "title_form" + + def form_valid(self, form): + # Fetch the old lead from the database + old_title = copy.copy(self.get_object().title) + + response = super().form_valid(form) + project = form.instance + + messenger( + MESSAGES.UPDATE_PROJECT_TITLE, + request=self.request, + user=self.request.user, + source=project, + related=old_title, + ) + + messages.success( + self.request, + _("Title has been updated"), + extra_tags=PROJECT_ACTION_MESSAGE_TAG, + ) + return response + + # CONTRACTS @@ -1244,6 +1274,7 @@ class AdminProjectDetailView( UpdatePAFApproversView, ReportFrequencyUpdate, UpdateLeadView, + UpdateProjectTitleView, UploadContractView, UploadDocumentView, UpdateAssignApproversView,