Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SC-82 Upload Documents (evaluation pack) #2013

Merged
merged 1 commit into from
Dec 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 56 additions & 0 deletions app/controllers/support/cases/document_uploads_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
module Support
class Cases::DocumentUploadsController < Cases::ApplicationController
before_action :set_current_case
before_action { @back_url = support_case_path(@current_case, anchor: "tasklist") }
before_action { @uploaded_files = current_case.upload_documents }
def edit
@document_uploader = current_case.document_uploader
@uploaded_files = current_case.upload_documents
end

def create
@document_uploader = current_case.document_uploader(document_uploader_params)
if @document_uploader.valid?
@document_uploader.save!
@current_case.update!(case_document_uploader_params)
redirect_to @back_url
else
render :edit
end
end

def destroy
@uploaded_document = Support::CaseUploadDocument.find(params[:document_id])
@support_document = Support::Document.find(@uploaded_document.attachable_id)
@back_url = edit_support_case_document_uploads_path
return unless params[:confirm]

@uploaded_document.destroy!
@support_document.destroy!

if @uploaded_files.empty?
reset_uploaded_documents
end
redirect_to edit_support_case_document_uploads_path,
notice: I18n.t("support.cases.upload_documents.flash.destroyed", name: @uploaded_document.file_name)
end

private

def set_current_case
@current_case = Support::Case.find(params[:case_id])
end

def document_uploader_params
params.fetch(:document_uploader, {}).permit(:has_uploaded_documents, files: [])
end

def case_document_uploader_params
params.require(:document_uploader).permit(:has_uploaded_documents)
end

def reset_uploaded_documents
@current_case.update!(has_uploaded_documents: nil)
end
end
end
1 change: 1 addition & 0 deletions app/controllers/support/document_downloads_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ class DocumentDownloadsController < Cases::ApplicationController
"Support::CaseAttachment",
"EnergyBill",
"Support::EmailTemplateAttachment",
"Support::CaseUploadDocument",
].freeze

def show
Expand Down
3 changes: 3 additions & 0 deletions app/models/support/case.rb
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ class Case < ApplicationRecord
include FileUploadable
include Surveyable
include Notifiable
include DocumentUploadable

belongs_to :category, class_name: "Support::Category", optional: true
belongs_to :query, class_name: "Support::Query", optional: true
Expand Down Expand Up @@ -63,6 +64,8 @@ class Case < ApplicationRecord

accepts_nested_attributes_for :hub_transition, allow_destroy: true, reject_if: :all_blank

has_many :upload_documents, class_name: "Support::CaseUploadDocument", foreign_key: :support_case_id

# Support level
#
# L1 - Advice and guidance only
Expand Down
20 changes: 20 additions & 0 deletions app/models/support/case/document_uploadable.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
module Support::Case::DocumentUploadable
extend ActiveSupport::Concern

def document_uploader(params = {})
Support::Case::DocumentUploader.new(support_case: self, **params)
end

def upload_document_files(files:)
return if files.blank?

files.each do |file|
upload_documents.create!(
attachable: Support::Document.create!(case: self, file_type: file.content_type, file:),
file_type: file.content_type,
file_name: file.original_filename,
file_size: file.size,
)
end
end
end
25 changes: 25 additions & 0 deletions app/models/support/case/document_uploader.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
class Support::Case::DocumentUploader
include ActiveModel::Model
include ActiveModel::Attributes
include ActiveModel::Validations

attribute :files
attribute :upload_document_files
attribute :support_case
attribute :has_uploaded_documents

validates :files, presence: true, if: -> { support_case.has_uploaded_documents.nil? }
validate :files_safe, if: -> { files.present? }
validates :has_uploaded_documents, presence: true

def save!
support_case.upload_document_files(files:)
end

private

def files_safe
results = files.map { |file| Support::VirusScanner.uploaded_file_safe?(file) }
errors.add(:files, I18n.t("support.case.label.case_files.errors.unsafe")) unless results.all?
end
end
10 changes: 10 additions & 0 deletions app/models/support/case_upload_document.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# frozen_string_literal: true

module Support
class CaseUploadDocument < ApplicationRecord
belongs_to :case, class_name: "Support::Case", foreign_key: :support_case_id
belongs_to :attachable, polymorphic: true, optional: true

delegate :file, :file_type, to: :attachable
end
end
38 changes: 38 additions & 0 deletions app/views/support/cases/document_uploads/_form.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<%= form_with model: @document_uploader, scope: :document_uploader, url: support_case_document_uploads_path,
html: { "data-controller" => "case-files" } do |form| %>

<h2 class="govuk-heading-m"><%= I18n.t("support.cases.upload_documents.choose_file_title") %></h2>

<%= form.govuk_error_summary %>

<span class="govuk-button govuk-button--secondary" role="button"
data-case-files-target="btnDisplayFileDialog">
<%= I18n.t("support.cases.upload_documents.button.choose_file") %>
</span>

<%= render "uploaded_documents" %>

<div class="govuk-form-group govuk-!-margin-top-7">
<fieldset class="govuk-fieldset">
<legend class="govuk-fieldset__legend govuk-fieldset__legend--s"><%= I18n.t("support.cases.upload_documents.file_upload_confirmation") %></legend>
<div class="govuk-radios">
<div class="govuk-radios__item">
<%= form.radio_button :has_uploaded_documents, true, checked: @current_case.has_uploaded_documents == true, class: "govuk-radios__input" %>
<%= form.label :has_uploaded_documents, "Yes, I have uploaded all documents", value: true, class: "govuk-label govuk-radios__label" %>
</div>
<div class="govuk-radios__item">
<%= form.radio_button :has_uploaded_documents, false, checked: @current_case.has_uploaded_documents == false, class: "govuk-radios__input" %>
<%= form.label :has_uploaded_documents, "No", value: false, class: "govuk-label govuk-radios__label" %>
</div>
</div>
</fieldset>
</div>

<div class="govuk-button-group flex-align-center">
<%= form.submit I18n.t("generic.button.next"), class: "govuk-button", role: "button", "data-action" => "case-files#submit", data: { disable_with: "Uploading..." } %>
<%= link_to I18n.t("generic.button.cancel"), @back_url, class: "govuk-link govuk-link--no-visited-state" %>
</div>

<%= form.govuk_file_field :files, multiple: true, include_hidden: false, class: "govuk-!-display-none", "data-case-files-target" => "filesField", form_group: { class: "govuk-!-display-none" } %>

<% end %>
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@

<div class="govuk-grid-row">
<div class="govuk-grid-column-two-thirds">
<h3 class="govuk-heading-s govuk-!-margin-bottom-2"><%= I18n.t("support.cases.upload_documents.file_uploaded") %></h3>
</div>
</div>

<div class="govuk-grid-row">
<div class="govuk-grid-column-two-thirds">
<div class="govuk-!-display-none" data-case-files-target="fileList">
<div data-case-files-target="filePreview">
<div data-case-files-target="previewTemplate">
<div class="case-files__file">
<span class="case-files__file-name" data-dz-name></span>
<div class="case-files__file-actions">
<span class="case-files__file-remove">
<a class="govuk-link govuk-link--no-visited-state" href="#" data-dz-remove><%= I18n.t("generic.button.delete") %></a>
</span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>

<div class="govuk-grid-row">
<div class="govuk-grid-column-two-thirds">
<% @uploaded_files.each do |uploaded_file| %>
<div class="case-files__file">
<span class="case-files__file-name"><%= link_to uploaded_file.file_name, support_document_download_path(uploaded_file, type: uploaded_file.class), class: "govuk-link", target: "_blank" %></span>
<div class="case-files__file-actions">
<span class="case-files__file-remove">
<%= link_to I18n.t("generic.button.delete"),
support_case_document_uploads_path(case_id: @current_case, document_id: uploaded_file),
method: :delete,
class: "govuk-link govuk-link--no-visited-state" %>
</span>
</div>
</div>
<% end %>
</div>
</div>
16 changes: 16 additions & 0 deletions app/views/support/cases/document_uploads/destroy.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<%= render partial: "support/cases/components/case_header", locals: { current_case: @current_case } %>

<h1 class="govuk-heading-l">
<%= I18n.t("support.cases.upload_documents.delete_confirmation", name:@uploaded_document.file_name) %>
</h1>

<div class="govuk-button-group flex-align-center">
<%= link_to I18n.t("generic.button.delete"),
support_case_document_uploads_path(@uploaded_document, case_id: @current_case, confirm: true, document_id: @uploaded_document.id),
method: :delete,
class: "govuk-button govuk-button--warning" %>

<%= link_to I18n.t("generic.button.cancel"),
edit_support_case_document_uploads_path(case_id: @current_case),
class: "govuk-link govuk-link--no-visited-state" %>
</div>
5 changes: 5 additions & 0 deletions app/views/support/cases/document_uploads/edit.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<%= render partial: "support/cases/components/case_header", locals: { current_case: @current_case } %>
<h1 class="govuk-heading-l"><%= I18n.t("support.cases.upload_documents.header") %></h1>
<p class="govuk-body-m govuk-!-static-margin-bottom-8"><%= I18n.t("support.cases.upload_documents.hint") %></p>

<%= render "form" %>
5 changes: 5 additions & 0 deletions app/views/support/cases/document_uploads/index.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<%= render "framework_requests/form",
route: "document_uploads",
verb: :post,
path: document_uploads_framework_requests_path,
hide_submit_button: true %>
11 changes: 10 additions & 1 deletion app/views/support/cases/show/_tasklist.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,16 @@
<%= govuk_task_list(id_prefix: "complete-evaluation") do |task_list|
task_list.with_item(title: I18n.t("support.case.label.tasklist.item.add_evaluators"), href: '#', status: govuk_tag(text: I18n.t("support.case.label.tasklist.status.to_do")))
task_list.with_item(title: I18n.t("support.case.label.tasklist.item.set_due_date"), href: edit_support_case_evaluation_due_dates_path(@current_case), status: @current_case.evaluation_due_date ? govuk_tag(text: I18n.t("support.case.label.tasklist.status.complete"), colour: "green") : govuk_tag(text: I18n.t("support.case.label.tasklist.status.to_do")))
task_list.with_item(title: I18n.t("support.case.label.tasklist.item.upload_documents"), href: '#', status: govuk_tag(text: I18n.t("support.case.label.tasklist.status.to_do")))

if @current_case.has_uploaded_documents == true
document_upload_Status = govuk_tag(text: I18n.t("support.case.label.tasklist.status.complete"), colour: "green")
elsif @current_case.has_uploaded_documents == false
document_upload_Status = govuk_tag(text: I18n.t("support.case.label.tasklist.status.in_progress"))
else
document_upload_Status = govuk_tag(text: I18n.t("support.case.label.tasklist.status.to_do"))
end

task_list.with_item(title: I18n.t("support.case.label.tasklist.item.upload_documents"), href: edit_support_case_document_uploads_path(@current_case), status: document_upload_Status)
task_list.with_item(title: I18n.t("support.case.label.tasklist.item.email_evaluators")) do | item |
item.with_status(text: I18n.t("support.case.label.tasklist.status.cannot_start"), cannot_start_yet: true)
end
Expand Down
15 changes: 15 additions & 0 deletions config/locales/en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1780,6 +1780,21 @@ en:
hint: For example, 27 3 2025
submit: Continue
cancel: Cancel
upload_documents:
header: Upload documents
hint: Upload documents to share with each evaluator.
choose_file_title: Upload a file
file_uploaded: File uploaded
file_upload_confirmation: Have you uploaded all documents?
radio_buttons:
yes: "Yes, I have uploaded all documents"
no: "No"
button:
choose_file: Choose file
flash:
destroyed: "%{name} successfully removed"
delete_confirmation: Are you sure you want to delete %{name}?
is_document_uploaded: Please select uploaded option
emails:
attachments:
attach_files: Attach files
Expand Down
8 changes: 8 additions & 0 deletions config/locales/validation/support/en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,14 @@ en:
attributes:
files:
blank: Select files to upload
support/case/document_uploader:
attributes:
files:
blank: Select files to upload
has_uploaded_documents:
blank: Please confirm that you uploaded all documents



forms:
rules:
Expand Down
1 change: 1 addition & 0 deletions config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,7 @@
resources :additional_contacts
resources :evaluators, except: %i[show]
resource :evaluation_due_dates, only: %i[edit update]
resource :document_uploads, except: %i[show]
resource :email, only: %i[create] do
scope module: :emails do
resources :content, only: %i[show], param: :template
Expand Down
13 changes: 13 additions & 0 deletions db/migrate/20241203125734_add_support_case_upload_documents.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
class AddSupportCaseUploadDocuments < ActiveRecord::Migration[7.2]
def change
create_table "support_case_upload_documents", id: :uuid do |t|
t.references "support_case", type: :uuid
t.string "file_type"
t.string "file_name"
t.bigint "file_size"
t.uuid "attachable_id"
t.string "attachable_type"
t.timestamps
end
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
class AddHasUploadedDocumentsToSupportCases < ActiveRecord::Migration[7.2]
def change
add_column :support_cases, :has_uploaded_documents, :boolean
end
end
15 changes: 14 additions & 1 deletion db/schema.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.

ActiveRecord::Schema[7.2].define(version: 2024_11_26_122758) do
ActiveRecord::Schema[7.2].define(version: 2024_12_09_104836) do
create_sequence "evaluation_refs"
create_sequence "framework_refs"

Expand Down Expand Up @@ -573,6 +573,18 @@
t.index ["support_organisation_id"], name: "index_support_case_organisations_on_support_organisation_id"
end

create_table "support_case_upload_documents", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
t.uuid "support_case_id"
t.string "file_type"
t.string "file_name"
t.bigint "file_size"
t.uuid "attachable_id"
t.string "attachable_type"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["support_case_id"], name: "index_support_case_upload_documents_on_support_case_id"
end

create_table "support_cases", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
t.string "ref"
t.uuid "category_id"
Expand Down Expand Up @@ -624,6 +636,7 @@
t.string "other_school_urns", default: [], array: true
t.boolean "is_evaluator", default: false
t.date "evaluation_due_date"
t.boolean "has_uploaded_documents"
t.index ["category_id"], name: "index_support_cases_on_category_id"
t.index ["existing_contract_id"], name: "index_support_cases_on_existing_contract_id"
t.index ["new_contract_id"], name: "index_support_cases_on_new_contract_id"
Expand Down
Loading
Loading