diff --git a/Gemfile b/Gemfile index 9293ef0c2..1d23cfed2 100644 --- a/Gemfile +++ b/Gemfile @@ -49,6 +49,7 @@ gem "rubocop-rspec" gem 'active_model_serializers', '>= 0.10.13' gem 'acts-as-list' gem 'aws-sdk-rails', '>= 3.8.0' +gem 'aws-sdk-s3' gem 'caracal', '>= 1.4.1' gem 'carrierwave', '>= 2.2.1' gem 'devise', '>= 4.8.1' diff --git a/Gemfile.lock b/Gemfile.lock index 8fbe99005..a0f39eaad 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -18,50 +18,51 @@ GEM aasm-diagram (0.1.3) aasm (~> 5.0, >= 4.12) ruby-graphviz (~> 1.2) - actioncable (7.1.1) - actionpack (= 7.1.1) - activesupport (= 7.1.1) + actioncable (7.1.2) + actionpack (= 7.1.2) + activesupport (= 7.1.2) nio4r (~> 2.0) websocket-driver (>= 0.6.1) zeitwerk (~> 2.6) - actionmailbox (7.1.1) - actionpack (= 7.1.1) - activejob (= 7.1.1) - activerecord (= 7.1.1) - activestorage (= 7.1.1) - activesupport (= 7.1.1) + actionmailbox (7.1.2) + actionpack (= 7.1.2) + activejob (= 7.1.2) + activerecord (= 7.1.2) + activestorage (= 7.1.2) + activesupport (= 7.1.2) mail (>= 2.7.1) net-imap net-pop net-smtp - actionmailer (7.1.1) - actionpack (= 7.1.1) - actionview (= 7.1.1) - activejob (= 7.1.1) - activesupport (= 7.1.1) + actionmailer (7.1.2) + actionpack (= 7.1.2) + actionview (= 7.1.2) + activejob (= 7.1.2) + activesupport (= 7.1.2) mail (~> 2.5, >= 2.5.4) net-imap net-pop net-smtp rails-dom-testing (~> 2.2) - actionpack (7.1.1) - actionview (= 7.1.1) - activesupport (= 7.1.1) + actionpack (7.1.2) + actionview (= 7.1.2) + activesupport (= 7.1.2) nokogiri (>= 1.8.5) + racc rack (>= 2.2.4) rack-session (>= 1.0.1) rack-test (>= 0.6.3) rails-dom-testing (~> 2.2) rails-html-sanitizer (~> 1.6) - actiontext (7.1.1) - actionpack (= 7.1.1) - activerecord (= 7.1.1) - activestorage (= 7.1.1) - activesupport (= 7.1.1) + actiontext (7.1.2) + actionpack (= 7.1.2) + activerecord (= 7.1.2) + activestorage (= 7.1.2) + activesupport (= 7.1.2) globalid (>= 0.6.0) nokogiri (>= 1.8.5) - actionview (7.1.1) - activesupport (= 7.1.1) + actionview (7.1.2) + activesupport (= 7.1.2) builder (~> 3.1) erubi (~> 1.11) rails-dom-testing (~> 2.2) @@ -71,22 +72,22 @@ GEM activemodel (>= 4.1) case_transform (>= 0.2) jsonapi-renderer (>= 0.1.1.beta1, < 0.3) - activejob (7.1.1) - activesupport (= 7.1.1) + activejob (7.1.2) + activesupport (= 7.1.2) globalid (>= 0.3.6) - activemodel (7.1.1) - activesupport (= 7.1.1) - activerecord (7.1.1) - activemodel (= 7.1.1) - activesupport (= 7.1.1) + activemodel (7.1.2) + activesupport (= 7.1.2) + activerecord (7.1.2) + activemodel (= 7.1.2) + activesupport (= 7.1.2) timeout (>= 0.4.0) - activestorage (7.1.1) - actionpack (= 7.1.1) - activejob (= 7.1.1) - activerecord (= 7.1.1) - activesupport (= 7.1.1) + activestorage (7.1.2) + actionpack (= 7.1.2) + activejob (= 7.1.2) + activerecord (= 7.1.2) + activesupport (= 7.1.2) marcel (~> 1.0) - activesupport (7.1.1) + activesupport (7.1.2) base64 bigdecimal concurrent-ruby (~> 1.0, >= 1.0.2) @@ -104,7 +105,7 @@ GEM aes_key_wrap (1.1.0) ast (2.4.2) aws-eventstream (1.2.0) - aws-partitions (1.848.0) + aws-partitions (1.849.0) aws-record (2.13.0) aws-sdk-dynamodb (~> 1, >= 1.85.0) aws-sdk-core (3.186.0) @@ -115,6 +116,9 @@ GEM aws-sdk-dynamodb (1.96.0) aws-sdk-core (~> 3, >= 3.184.0) aws-sigv4 (~> 1.1) + aws-sdk-kms (1.72.0) + aws-sdk-core (~> 3, >= 3.184.0) + aws-sigv4 (~> 1.1) aws-sdk-rails (3.9.0) aws-record (~> 2) aws-sdk-ses (~> 1, >= 1.50.0) @@ -123,13 +127,17 @@ GEM aws-sessionstore-dynamodb (~> 2) concurrent-ruby (~> 1) railties (>= 5.2.0) + aws-sdk-s3 (1.136.0) + aws-sdk-core (~> 3, >= 3.181.0) + aws-sdk-kms (~> 1) + aws-sigv4 (~> 1.6) aws-sdk-ses (1.56.0) aws-sdk-core (~> 3, >= 3.184.0) aws-sigv4 (~> 1.1) aws-sdk-sesv2 (1.41.0) aws-sdk-core (~> 3, >= 3.184.0) aws-sigv4 (~> 1.1) - aws-sdk-sqs (1.65.0) + aws-sdk-sqs (1.67.0) aws-sdk-core (~> 3, >= 3.184.0) aws-sigv4 (~> 1.1) aws-sessionstore-dynamodb (2.1.0) @@ -241,7 +249,7 @@ GEM activesupport (>= 6.0.0) railties (>= 6.0.0) io-console (0.6.0) - irb (1.8.3) + irb (1.9.0) rdoc reline (>= 0.3.8) jbuilder (2.11.5) @@ -279,7 +287,7 @@ GEM rb-fsevent (~> 0.10, >= 0.10.3) rb-inotify (~> 0.9, >= 0.9.10) logstop (0.3.1) - loofah (2.21.4) + loofah (2.22.0) crass (~> 1.0.2) nokogiri (>= 1.12.0) mail (2.8.1) @@ -302,7 +310,7 @@ GEM multi_xml (0.6.0) multipart-post (2.3.0) mutex_m (0.2.0) - net-imap (0.4.4) + net-imap (0.4.5) date net-protocol net-pop (0.1.2) @@ -356,7 +364,7 @@ GEM public_suffix (5.0.3) puma (6.4.0) nio4r (~> 2.0) - racc (1.7.2) + racc (1.7.3) rack (2.2.8) rack-cors (2.0.1) rack (>= 2.0.0) @@ -369,20 +377,20 @@ GEM rackup (1.0.0) rack (< 3) webrick - rails (7.1.1) - actioncable (= 7.1.1) - actionmailbox (= 7.1.1) - actionmailer (= 7.1.1) - actionpack (= 7.1.1) - actiontext (= 7.1.1) - actionview (= 7.1.1) - activejob (= 7.1.1) - activemodel (= 7.1.1) - activerecord (= 7.1.1) - activestorage (= 7.1.1) - activesupport (= 7.1.1) + rails (7.1.2) + actioncable (= 7.1.2) + actionmailbox (= 7.1.2) + actionmailer (= 7.1.2) + actionpack (= 7.1.2) + actiontext (= 7.1.2) + actionview (= 7.1.2) + activejob (= 7.1.2) + activemodel (= 7.1.2) + activerecord (= 7.1.2) + activestorage (= 7.1.2) + activesupport (= 7.1.2) bundler (>= 1.15.0) - railties (= 7.1.1) + railties (= 7.1.2) rails-controller-testing (1.0.5) actionpack (>= 5.0.1.rc1) actionview (>= 5.0.1.rc1) @@ -399,9 +407,9 @@ GEM rails-html-sanitizer (1.6.0) loofah (~> 2.21) nokogiri (~> 1.14) - railties (7.1.1) - actionpack (= 7.1.1) - activesupport (= 7.1.1) + railties (7.1.2) + actionpack (= 7.1.2) + activesupport (= 7.1.2) irb rackup (>= 1.0.0) rake (>= 12.2) @@ -421,7 +429,7 @@ GEM redis-namespace (1.11.0) redis (>= 4) regexp_parser (2.8.2) - reline (0.3.9) + reline (0.4.0) io-console (~> 0.5) request_store (1.5.1) rack (>= 1.4) @@ -566,6 +574,7 @@ DEPENDENCIES acts-as-list acts-as-taggable-on aws-sdk-rails (>= 3.8.0) + aws-sdk-s3 bootsnap brakeman bullet diff --git a/app/assets/stylesheets/site.scss b/app/assets/stylesheets/site.scss index 6323afc6e..361d59a9e 100644 --- a/app/assets/stylesheets/site.scss +++ b/app/assets/stylesheets/site.scss @@ -147,7 +147,7 @@ footer { .well { border: 1px solid #d6d7d9; padding: 20px; - margin: 10px 0; + margin-bottom: 10px; overflow-wrap: break-word; } diff --git a/app/controllers/admin/cx_collection_details_controller.rb b/app/controllers/admin/cx_collection_details_controller.rb index 6756b3a37..7b5b48437 100644 --- a/app/controllers/admin/cx_collection_details_controller.rb +++ b/app/controllers/admin/cx_collection_details_controller.rb @@ -1,5 +1,5 @@ class Admin::CxCollectionDetailsController < AdminController - before_action :set_cx_collection_detail, only: %i[ show edit upload update destroy ] + before_action :set_cx_collection_detail, only: %i[ show edit upload upload_csv update destroy ] before_action :set_cx_collections, only: %i[ new edit upload ] def index @@ -26,8 +26,8 @@ def create respond_to do |format| if @cx_collection_detail.save - format.html { redirect_to admin_cx_collection_detail_url(@cx_collection_detail), notice: "Cx collection detail was successfully created." } - format.json { render :show, status: :created, location: @cx_collection_detail } + format.html { redirect_to upload_admin_cx_collection_detail_url(@cx_collection_detail), notice: "CX Collection Detail was successfully created." } + format.json { render :upload, status: :created, location: @cx_collection_detail } else format.html { render :new, status: :unprocessable_entity } format.json { render json: @cx_collection_detail.errors, status: :unprocessable_entity } @@ -38,7 +38,7 @@ def create def update respond_to do |format| if @cx_collection_detail.update(cx_collection_detail_params) - format.html { redirect_to admin_cx_collection_detail_url(@cx_collection_detail), notice: "Cx collection detail was successfully updated." } + format.html { redirect_to admin_cx_collection_detail_url(@cx_collection_detail), notice: "CX Collection Detail was successfully updated." } format.json { render :show, status: :ok, location: @cx_collection_detail } else format.html { render :edit, status: :unprocessable_entity } @@ -51,11 +51,32 @@ def destroy @cx_collection_detail.destroy respond_to do |format| - format.html { redirect_to cx_collection_details_url, notice: "Cx collection detail was successfully destroyed." } + format.html { redirect_to cx_collection_details_url, notice: "CX Collection Detail was successfully destroyed." } format.json { head :no_content } end end + # Handle a large-ish csv upload (5+ MB) to S3 + def upload_csv + file = params[:file] # Assuming the file comes from a form field named 'file' + bucket = ENV.fetch("S3_UPLOADS_AWS_BUCKET_NAME") + + s3 = Aws::S3::Resource.new + key = "cx_data_collections/cx-upload-#{Time.now.to_i}-#{file.original_filename}}" + obj = s3.bucket(bucket).object(file.original_filename) + # Upload the file + response = obj.upload_file(file.path) + + CxCollectionDetailUpload.create!({ + user_id: current_user.id, + cx_collection_detail_id: @cx_collection_detail.id, + size: obj.size, + key: obj.key, + }) + + render :upload, message: 'File successfully uploaded' + end + private def set_cx_collection_detail @cx_collection_detail = CxCollectionDetail.find(params[:id]) @@ -63,7 +84,7 @@ def set_cx_collection_detail def set_cx_collections if service_manager_permissions? - @cx_collections = CxCollection.all.includes(:organization) + @cx_collections = CxCollection.all.includes(:organization).order('organizations.abbreviation') else @cx_collections = current_user.organization.cx_collections end diff --git a/app/controllers/admin/service_providers_controller.rb b/app/controllers/admin/service_providers_controller.rb index 6bac9ae62..d470b9533 100644 --- a/app/controllers/admin/service_providers_controller.rb +++ b/app/controllers/admin/service_providers_controller.rb @@ -111,9 +111,6 @@ def service_provider_params :description, :notes, :slug, - :department, - :department_abbreviation, - :bureau, :inactive, :new, :tag_list, diff --git a/app/models/cx_collection_detail_upload.rb b/app/models/cx_collection_detail_upload.rb new file mode 100644 index 000000000..88a11c4aa --- /dev/null +++ b/app/models/cx_collection_detail_upload.rb @@ -0,0 +1,4 @@ +class CxCollectionDetailUpload < ApplicationRecord + belongs_to :user + belongs_to :cx_collection_detail +end diff --git a/app/models/website.rb b/app/models/website.rb index 4e7c75db7..c2ba61b60 100644 --- a/app/models/website.rb +++ b/app/models/website.rb @@ -191,7 +191,7 @@ def validate_domain_format end def validate_domain_suffix - errors.add(:domain, 'domain must have a valid suffix, like .gov or .mil') unless domain.present? && APPROVED_DOMAINS.any? { |word| domain.end_with?(word) } + errors.add(:domain, 'domain must have a valid suffix, like .gov or .mil') unless domain.present? && APPROVED_WEBSITE_DOMAINS.any? { |word| domain.end_with?(word) } end def site_scanner_json_request diff --git a/app/serializers/service_serializer.rb b/app/serializers/service_serializer.rb index 8de965232..728944a78 100644 --- a/app/serializers/service_serializer.rb +++ b/app/serializers/service_serializer.rb @@ -19,8 +19,6 @@ class ServiceSerializer < ActiveModel::Serializer :transactional, :notes, :hisp, - :department, - :bureau, :service_abbreviation, :service_slug, :service_owner_email, diff --git a/app/views/admin/cx_collection_details/_form.html.erb b/app/views/admin/cx_collection_details/_form.html.erb index 65ae955cb..a2ec1aaea 100644 --- a/app/views/admin/cx_collection_details/_form.html.erb +++ b/app/views/admin/cx_collection_details/_form.html.erb @@ -1,4 +1,4 @@ -<%= form_with(model: cx_collection_detail, url: (cx_collection_detail.persisted? ? admin_cx_collection_detail_path(cx_collection_detail) : admin_cx_collection_details_path) ) do |form| %> +<%= form_with(model: cx_collection_detail, url: (cx_collection_detail.persisted? ? admin_cx_collection_detail_path(cx_collection_detail) : admin_cx_collection_details_path), class: "usa-form") do |form| %> <% if cx_collection_detail.errors.any? %>

<%= pluralize(cx_collection_detail.errors.count, "error") %> prohibited this cx_collection_detail from being saved:

@@ -15,26 +15,36 @@ <%= form.label :cx_collection_id, class: "usa-label" %> <%= form.hidden_field :cx_collection_id, class: "usa-input", value: cx_collection_detail.cx_collection_id %> <%= form.select :cx_collection_id, - cx_collections.map { |collection| ["#{collection.name} - #{collection.organization.name}", collection.id]}, + cx_collections.map { |collection| ["#{collection.organization.abbreviation} - #{collection.organization.name} - #{collection.service.name}", collection.id]}, { include_blank: true }, class: "usa-select" %>
- <%= form.label :transaction_point, class: "usa-label" %> + <%= form.label :transaction_point, "Type of Feedback Survey", class: "usa-label" %> +
+ OMB Circular A-11 Section 280 lists three types of customer feedback survey: post-interaction, post-service journey (at the end of a service journey), and relational. Select the best description for your survey. +
<%= form.select :transaction_point, - [:post_interaction, :post_service_journey, :relational], + [ + ["Post-interaction", :post_interaction], + ["Post-service journey", :post_service_journey], + ["Relational", :relational] + ], { include_blank: true }, class: "usa-select" %>
- <%= form.label :channel, class: "usa-label" %> + <%= form.label :channel, "Channel of Survey", class: "usa-label" %> +
+ Tell us how you deployed the survey. What is the channel you used to reach your respondents? +
<%= form.select :channel, [:computer, :mobile, :paper, :in_person], { prompt: "What type of response channel?" }, class: "usa-select" %>
- <%= form.label :service_stage_id, class: "usa-label" %> + <%= form.label :service_stage_id, "Stage of Service Journey", class: "usa-label" %> <% if cx_collection_detail.service %> <%= form.select :service_stage_id, options_for_select(cx_collection_detail.cx_collection.service.service_stages.map { |stage| [stage.name, stage.id]}), { include_blank: true }, @@ -48,51 +58,82 @@
<%= form.label :survey_type, class: "usa-label" %> - <%= form.select :survey_type, [["A-11 7 driver questions", :seven_questions], ["A-11 Yes/no thumbs buttons", :yes_no_buttons] ], + +
+ OMB Circular A-11 Section 280 allows for two types of response scale for the required Trust question. + Please select the response scale for your survey here. +
+ + <%= form.select :survey_type, [["Thumbs Up/Down", :thumbs_up_down], ["5-point Likert Scale", :likert_scale]], { include_blank: true }, { class: "usa-select" } %>
<%= form.label :survey_title, class: "usa-label" %> +
+ Please provide a short, succinct, public-facing title for your feedback survey. +
<%= form.text_area :survey_title, class: "usa-input" %>
<%= form.label :omb_control_number, class: "usa-label" %> +
+ The OMB Control Number helps us identify the PRA/A-11 Gen IC approval for this survey. +
<%= form.text_field :omb_control_number, class: "usa-input" %>
<%= form.label :trust_question_text, class: "usa-label" %> +
+ Copy and paste the text of the required Trust question in your feedback survey here +
<%= form.text_area :trust_question_text, class: "usa-input" %>
-
- <%= form.label :federal_register_url, class: "usa-label" %> - <%= form.text_field :federal_register_url, class: "usa-input" %> -
-
<%= form.label :volume_of_customers, class: "usa-label" %> +
+ This is your best estimate of the number of customers in your service for this quarter. +
<%= form.number_field :volume_of_customers, class: "usa-input" %>
<%= form.label :volume_of_customers_provided_survey_opportunity, class: "usa-label" %> +
+ This is your best estimate of the number of customers offered the opportunity to complete a feedback survey. +
<%= form.number_field :volume_of_customers_provided_survey_opportunity, class: "usa-input" %>
<%= form.label :volume_of_respondents, class: "usa-label" %> +
+ This is your best estimate of the number of respondents who completed the feedback survey. In general, this should be a count of the number of responses your are responses. +
<%= form.number_field :volume_of_respondents, class: "usa-input" %>
-
- <%= form.label :reflection_text, class: "usa-label" %> +
+ <%= form.label :reflection_text, "Survey reflection", class: "usa-label" %> +
+ Tell us what you learned from the survey? (100 words) +
<%= form.text_area :reflection_text, class: "usa-textarea" %>
+
+
+

+ Creating this Collection Detail will allow you to submit the corresponding survey data as a CSV file on the next page. + You may still edit after you have created the collection detail. +

+
+
+

<%= form.submit class: "usa-button" %>

diff --git a/app/views/admin/cx_collection_details/edit.html.erb b/app/views/admin/cx_collection_details/edit.html.erb index 256da82e4..a93cd016d 100644 --- a/app/views/admin/cx_collection_details/edit.html.erb +++ b/app/views/admin/cx_collection_details/edit.html.erb @@ -3,7 +3,7 @@ <% end %>

- <%= link_to admin_cx_collection_path(@cx_collection_detail.cx_collection) do %> + <%= link_to admin_cx_collection_detail_path(@cx_collection_detail) do %> Back to CX collection detail <% end %> @@ -14,13 +14,13 @@ cx_collections: @cx_collections %>
+
-

- <%= link_to "Show this cx collection detail", admin_cx_collection_detail_path(@cx_collection_detail) %> | - <%= link_to "Back to cx collection details", admin_cx_collection_details_path %> -
-
- <%= button_to "Destroy this cx collection detail", admin_cx_collection_detail_path(@cx_collection_detail), method: :delete, class: "usa-button usa-button--secondary" %> -
-
+
+
+ <%= button_to "Destroy this cx collection detail", admin_cx_collection_detail_path(@cx_collection_detail), method: :delete, class: "usa-button usa-button--secondary" %> +
+ +
+
\ No newline at end of file diff --git a/app/views/admin/cx_collection_details/show.html.erb b/app/views/admin/cx_collection_details/show.html.erb index 8427d06a0..325d125d1 100644 --- a/app/views/admin/cx_collection_details/show.html.erb +++ b/app/views/admin/cx_collection_details/show.html.erb @@ -1,9 +1,9 @@ <% content_for :navigation_title do %> <% if true || service_permissions?(service: @service) %>
- <%= link_to upload_admin_cx_collection_detail_path(@cx_collection_detail), class: "usa-button usa-button-inverted" do %> + <%= link_to upload_admin_cx_collection_detail_path(@cx_collection_detail), class: "usa-button usa-button--primary" do %> - Upload + Upload Responses <% end %> <%= link_to edit_admin_cx_collection_detail_path(@cx_collection_detail), class: "usa-button usa-button-inverted" do %> @@ -44,7 +44,7 @@

Channel: - <%= @cx_collection_detail.transaction_point %> + <%= @cx_collection_detail.channel %>

@@ -52,6 +52,9 @@ Service stage: <% if @cx_collection_detail.service_stage %> <%= link_to(@cx_collection_detail.service_stage.name, admin_service_service_stage_path(@cx_collection_detail.service_stage)) || 'Select a Service Stage' %> + <% else %> + <%= link_to "Service Stage", admin_service_service_stages_path(@cx_collection_detail.service) %> + is not defined. <% end %>

@@ -78,12 +81,6 @@ <%= @cx_collection_detail.omb_control_number %>

-

- Federal register url: - <%= @cx_collection_detail.federal_register_url %> - -

-

Reflection text: <%= @cx_collection_detail.reflection_text %> diff --git a/app/views/admin/cx_collection_details/upload.html.erb b/app/views/admin/cx_collection_details/upload.html.erb index 5001ef776..6a107a060 100644 --- a/app/views/admin/cx_collection_details/upload.html.erb +++ b/app/views/admin/cx_collection_details/upload.html.erb @@ -11,14 +11,30 @@ Upload CX Collection Data <% end %> -

+

<%= link_to admin_cx_collection_detail_path(@cx_collection_detail) do %> Back to CX Data Collection Detail <% end %> +
+ +

+ Before you attach your survey dataset below. +
+ Please review this checklist and make sure the excel meet these formatting requirements: +
+ Is it named correctly. Examples - +
+ Is it a CSV formatted file? +
+ Are the 14 columns? +
+ Is each row a response to the feedback survey. + Does it generally look like + <%= link_to "this", "https://github.com/gsa/touchpoints/wiki/" %>?

-<%= form_with(model: @cx_collection_detail, url: (@cx_collection_detail.persisted? ? admin_cx_collection_detail_path(@cx_collection_detail) : admin_cx_collection_details_path) ) do |form| %> +<%= form_with url: post_csv_admin_cx_collection_detail_path, method: :post, local: true, multipart: true do |form| %> <% if @cx_collection_detail.errors.any? %>

<%= pluralize(@cx_collection_detail.errors.count, "error") %> prohibited this cx_collection_detail from being saved:

@@ -34,10 +50,48 @@
<%= form.label :logo_display, "Upload CX Data Collection", class: "usa-label text-uppercase font-body-3xs", for: "file-input-single" %> - <%= form.file_field :logo, class: "usa-file-input display-logo", data_url: "" %> + <%= form.file_field :file, class: "usa-file-input display-logo", data_url: "" %>

<%= form.submit class: "usa-button" %>

<% end %> + +<% uploads = CxCollectionDetailUpload.where(cx_collection_detail_id: @cx_collection_detail.id) %> + + + + + + + + + + + + + <% uploads.each do |upload| %> + + + + + + + + <% end %> + +
UserFile pathSizeTimestamp
+ <%= upload.user.email %> + + <%= link_to(upload.key, upload.key) %> + + <%= upload.size %> + + <%= upload.created_at %> + + <%= link_to "Process responses file", admin_cx_collection_detail_path(@cx_collection_detail), method: :post %> +
+ + +
diff --git a/app/views/admin/cx_collections/_form.html.erb b/app/views/admin/cx_collections/_form.html.erb index dc70b1c9c..d59d581d6 100644 --- a/app/views/admin/cx_collections/_form.html.erb +++ b/app/views/admin/cx_collections/_form.html.erb @@ -1,4 +1,4 @@ -<%= form_with(model: cx_collection, url: (cx_collection.persisted? ? admin_cx_collection_path(cx_collection) : admin_cx_collections_path), local: true, data: { turbo: false }) do |form| %> +<%= form_with(model: cx_collection, url: (cx_collection.persisted? ? admin_cx_collection_path(cx_collection) : admin_cx_collections_path), class: "usa-form", local: true, data: { turbo: false }) do |form| %> <% if cx_collection.errors.any? %>

<%= pluralize(cx_collection.errors.count, "error") %> prohibited this cx_collection from being saved:

@@ -27,7 +27,7 @@
<%= form.label :service_provider_id, "HISP Service Provider", class: "usa-label" %> - <%= form.select :service_provider_id, ServiceProvider.all.includes(:organization).map { |h| ["#{h.organization.abbreviation} - #{h.organization.name} - #{h.name}", h.id] }, { include_blank: true }, { class: "usa-select", required: true } %> + <%= form.select :service_provider_id, ServiceProvider.all.includes(:organization).order("organizations.abbreviation", :name).map { |h| ["#{h.organization.abbreviation} - #{h.organization.name} - #{h.name}", h.id] }, { include_blank: true }, { class: "usa-select", required: true } %>
@@ -37,12 +37,12 @@
<%= form.label :fiscal_year, class: "usa-label" %> - <%= form.text_field :fiscal_year, class: "usa-input", required: true %> + <%= form.select :fiscal_year, options_for_select([2024, 2025], 2024), {}, class: "usa-select", required: true %>
<%= form.label :quarter, class: "usa-label" %> - <%= form.number_field :quarter, class: "usa-input", required: true, min: 1, max: 4 %> + <%= form.select :quarter, options_for_select([1, 2, 3, 4]), {}, class: "usa-select", required: true %>
@@ -62,7 +62,7 @@
<%= form.label :reflection, 'Reflection text', class: "usa-label" %>
- Please limit to 100 words. + Tell us what customer service improvements you were able to complete based on this quarter’s survey results. Please limit to 150 words.
<%= form.text_area :reflection, class: "usa-textarea" %>
@@ -79,6 +79,17 @@
<% end %> + <% if !cx_collection.persisted? %> +
+
+
+

+ After creating this collection, you can add survey results in the following screen. +

+
+
+ <% end %> +

<%= form.submit class: "usa-button" %>

diff --git a/app/views/admin/cx_collections/show.html.erb b/app/views/admin/cx_collections/show.html.erb index 966c9b74e..9cbc43649 100644 --- a/app/views/admin/cx_collections/show.html.erb +++ b/app/views/admin/cx_collections/show.html.erb @@ -89,8 +89,8 @@
-

- Services +

+ Collection details (<%= @cx_collection.cx_collection_details.size %>) @@ -98,23 +98,41 @@

- Add a Service detail reporting page for each touchpoint available within a HISP service. + Add a reporting page for each touchpoint available within a service.

-
    - <% @cx_collection.cx_collection_details.order(:channel).each do |cx_collection| %> -
  • - <%= link_to ("#{cx_collection.try(:service).try(:name)}"), admin_cx_collection_detail_path(cx_collection) %> · - <%= cx_collection.channel %> -
  • - <% end %> -
- <% if @cx_collection.draft? %> +
+ + + + + + + + + + <% @cx_collection.cx_collection_details.order(:channel).each do |cx_collection| %> + + + + + + <% end %> + +
ServiceTransaction pointChannel
+ <%= cx_collection.try(:service).try(:name) %> + + <%= link_to cx_collection.transaction_point, admin_cx_collection_detail_path(cx_collection) %> + + <%= cx_collection.channel %> +
+
+ <%- if @cx_collection.draft? %>

<%= link_to new_admin_cx_collection_detail_path(collection_id: @cx_collection.id), class: "usa-button usa-button--outline" do %> - Add a Service to report on + Add detail record <% end %>

<% end %> @@ -147,11 +165,8 @@

-
<%= render 'components/step_indicator', collection: @cx_collection %>

- <%= label_tag :collection_status, nil, class: "usa-label" %> -
<%= render 'components/collection_status_tag', collection: @cx_collection %>

diff --git a/app/views/admin/forms/delivery.html.erb b/app/views/admin/forms/delivery.html.erb index 2a4e26cd4..b82eb41da 100644 --- a/app/views/admin/forms/delivery.html.erb +++ b/app/views/admin/forms/delivery.html.erb @@ -65,7 +65,7 @@


-
+
How will users access this survey?
Delivery methods diff --git a/app/views/admin/forms/index.html.erb b/app/views/admin/forms/index.html.erb index b62b6f343..c4db58003 100644 --- a/app/views/admin/forms/index.html.erb +++ b/app/views/admin/forms/index.html.erb @@ -90,7 +90,7 @@
- <% if @service_provider.persisted? %> -
-
-
- <%= render 'admin/service_providers/service_provider_managers', service: @service_provider, service_provider_manager_options: @service_provider_manager_options %> -
-
-
- <% end %>
<%= form.label :notes, class: "usa-label" %> @@ -48,7 +39,7 @@
<% if service_manager_permissions? %> -
+
Notice: These are experimental fields, used to generate <%= link_to "a 2x2 based on data", quadrants_admin_service_providers_path %>. @@ -74,25 +65,11 @@ class: "usa-select" %>
-
- <%= form.label :department, class: "usa-label" %> - <%= form.text_field :department, class: "usa-input" %> -
- -
- <%= form.label :department_abbreviation, class: "usa-label" %> - <%= form.text_field :department_abbreviation, class: "usa-input" %> -
- -
- <%= form.label :bureau, class: "usa-label" %> - <%= form.text_field :bureau, class: "usa-input" %> -
- -
- <%= form.label :bureau_abbreviation, class: "usa-label" %> - <%= form.text_field :bureau_abbreviation, class: "usa-input" %> -
+ <% if @service_provider.persisted? %> +
+ <%= render 'admin/service_providers/service_provider_managers', service: @service_provider, service_provider_manager_options: @service_provider_manager_options %> +
+ <% end %>
<%= form.label :slug, class: "usa-label" %> diff --git a/app/views/admin/service_providers/_service_provider_managers.html.erb b/app/views/admin/service_providers/_service_provider_managers.html.erb index fbef7dde1..6d05adf4f 100644 --- a/app/views/admin/service_providers/_service_provider_managers.html.erb +++ b/app/views/admin/service_providers/_service_provider_managers.html.erb @@ -1,27 +1,27 @@
-

Service Provider Managers

+ <%= label_tag :portfolio_manager_email, "Service Provider Managers", class: "usa-label" %>

-

    - <% @service_provider.service_provider_managers.each do |manager| %> -
  • - - <%= manager.email %> - -   - - - -
  • - <% end %> -
-

+

    + <% @service_provider.service_provider_managers.each do |manager| %> +
  • + + <%= manager.email %> + +   + + + +
  • + <% end %> +
+

+ <%= select_tag :service_manager_id, + options_for_select(@service_provider_manager_options.map { |u| [u.email, u.id] }), + { prompt: "Select a Manager", class: "usa-select add-service-manager" } %>
- <%= select_tag :service_manager_id, - options_for_select(@service_provider_manager_options.map { |u| [u.email, u.id] }), - { prompt: "Select a Manager", class: "usa-select add-service-manager" } %>
diff --git a/app/views/admin/service_providers/index.html.erb b/app/views/admin/service_providers/index.html.erb index 3f70367d0..247550e77 100644 --- a/app/views/admin/service_providers/index.html.erb +++ b/app/views/admin/service_providers/index.html.erb @@ -69,7 +69,7 @@

<%= link_to admin_hisps_path(format: :csv), class: "usa-button usa-button--outline" do %> - Download as hisps.csv + Download hisps.csv <% end %> - used on performance.gov/cx

diff --git a/app/views/admin/service_providers/show.html.erb b/app/views/admin/service_providers/show.html.erb index 9f6628f44..c8d79b984 100644 --- a/app/views/admin/service_providers/show.html.erb +++ b/app/views/admin/service_providers/show.html.erb @@ -15,19 +15,20 @@ <% end %>

-<% if @service_provider.inactive? %> -
-
-

Inactive

-

- This Service Provider is no longer active. -

-
-
-<% end %> -
+ + <% if @service_provider.inactive? %> +
+
+

Inactive

+

+ This Service Provider is no longer active. +

+
+
+ <% end %> + <% if @service_provider.new? %>

@@ -99,21 +100,6 @@ <%= @service_provider.portfolio_manager_email %>

-

- Department: - <%= @service_provider.department %> -

- -

- Department abbreviation: - <%= @service_provider.department_abbreviation %> -

- -

- Bureau: - <%= @service_provider.bureau %> -

-

Slug: <%= @service_provider.slug %> diff --git a/app/views/admin/service_stages/index.html.erb b/app/views/admin/service_stages/index.html.erb index b098ae4f9..c616ecd61 100644 --- a/app/views/admin/service_stages/index.html.erb +++ b/app/views/admin/service_stages/index.html.erb @@ -2,7 +2,7 @@ Service Stages for: <%= @service.name %> <% end %>

- <%= link_to admin_services_path(@service) do %> + <%= link_to admin_services_path do %> Back to Services <% end %> diff --git a/app/views/admin/services/_form.html.erb b/app/views/admin/services/_form.html.erb index a061339a3..3a6392613 100644 --- a/app/views/admin/services/_form.html.erb +++ b/app/views/admin/services/_form.html.erb @@ -239,16 +239,6 @@

<% if service.persisted? && admin_permissions? %> -
- <%= form.label :department, class: "usa-label" %> - <%= form.text_field :department, class: "usa-input", placeholder: "Department" %> -
- -
- <%= form.label :bureau, class: "usa-label" %> - <%= form.text_field :bureau, class: "usa-input", placeholder: "Bureau" %> -
-
<%= form.label :service_abbreviation, class: "usa-label" %> <%= form.text_field :service_abbreviation, class: "usa-input", placeholder: "service_abbreviation" %> diff --git a/app/views/admin/services/show.html.erb b/app/views/admin/services/show.html.erb index ce3a2c06c..ca090ee0f 100644 --- a/app/views/admin/services/show.html.erb +++ b/app/views/admin/services/show.html.erb @@ -69,16 +69,15 @@ <%= @service.year_designated? ? @service.year_designated : "---" %>

- Description + Short Description
- <%= @service.description? ? to_markdown(@service.description) : "---" %> + <%= @service.short_description? ? to_markdown(@service.short_description) : "---" %>

- Short Description + Description
- <%= @service.short_description? ? to_markdown(@service.short_description) : "---" %> + <%= @service.description? ? to_markdown(@service.description) : "---" %>

-

Service type
@@ -172,23 +171,19 @@

- Service Homepage URL -
- <%= link_to @service.homepage_url, @service.homepage_url %> + <%= label_tag :homepage_url, "Service Homepage URL", class: "usa-label" %> + <%= text_field_tag :homepage_url, @service.homepage_url, class: "usa-input", disabled: true %>

- Service URL -
- <%= link_to @service.url, @service.url %> + <%= label_tag :url, "Service URL", class: "usa-label" %> + <%= text_field_tag :url, @service.url, class: "usa-input", disabled: true %>

- What is the estimated annual customer volume? -
- <%= @service.estimated_annual_volume_of_customers %> + <%= label_tag :estimated_annual_volume_of_customers, "What is the estimated annual customer volume?", class: "usa-label" %> + <%= text_field_tag :estimated_annual_volume_of_customers, @service.estimated_annual_volume_of_customers, class: "usa-input", disabled: true %>

- Notes -
+ <%= label_tag :notes, nil, class: "usa-label" %> <%= to_markdown(@service.notes) || "empty" %>

@@ -251,22 +246,12 @@
<% end %> -
+
This information is for performance.gov reporting purposes.
-

- Department -
- <%= @service.department %> -

-

- Bureau -
- <%= @service.bureau %> -

Service abbreviation
diff --git a/app/views/components/_collection_status_tag.html.erb b/app/views/components/_collection_status_tag.html.erb index ea3981d00..7d20af002 100644 --- a/app/views/components/_collection_status_tag.html.erb +++ b/app/views/components/_collection_status_tag.html.erb @@ -1,3 +1,3 @@ - + <%= collection.aasm_state %> diff --git a/app/views/components/forms/edit/_builder.html.erb b/app/views/components/forms/edit/_builder.html.erb index 673151f87..ecdd00221 100644 --- a/app/views/components/forms/edit/_builder.html.erb +++ b/app/views/components/forms/edit/_builder.html.erb @@ -55,9 +55,13 @@ - -

- +

+
+ saved @@ -65,9 +69,11 @@ <%= @disclaimer_text_limit %> <%= t :characters_allowed %> -
<%= form.disclaimer_text.present? ? sanitize(form.disclaimer_text) : 'Survey Disclaimer Text' %>
-

-
+
+ <%= form.disclaimer_text.present? ? sanitize(form.disclaimer_text) : 'Survey Disclaimer Text' %> +
+
+
@@ -82,7 +88,7 @@ $(function() { $(".question-option-edit").hide(); - <% if form_permissions?(form: form) %> + <%- if form_permissions?(form: form) %> $('.survey-title-input').on("blur", function(event) { event.preventDefault(); $('.usa-hint.save-notice.survey-title').show(); diff --git a/app/views/components/forms/question_types/_icon_checkboxes.html.erb b/app/views/components/forms/question_types/_icon_checkboxes.html.erb index c13fe1324..5316c2d69 100644 --- a/app/views/components/forms/question_types/_icon_checkboxes.html.erb +++ b/app/views/components/forms/question_types/_icon_checkboxes.html.erb @@ -19,7 +19,17 @@ <%= label_tag(nil, for: @option_id, class: "usa-checkbox__label") do %>

diff --git a/app/views/components/widget/_widget.css.erb b/app/views/components/widget/_widget.css.erb index 916934ab5..0e9afbde7 100644 --- a/app/views/components/widget/_widget.css.erb +++ b/app/views/components/widget/_widget.css.erb @@ -4566,6 +4566,10 @@ padding-left: 1rem; } +.touchpoint-form .question-options { + clear: both; +} + .touchpoint-form { max-width: 35em; margin-left: auto; diff --git a/config/environments/test.rb b/config/environments/test.rb index f582fa6f3..d43e41157 100644 --- a/config/environments/test.rb +++ b/config/environments/test.rb @@ -7,14 +7,8 @@ # your test database is "scratch space" for the test suite and is wiped # and recreated between test runs. Don't rely on the data there! require 'active_record' -require 'bullet' Rails.application.configure do - config.after_initialize do - Bullet.enable = true - Bullet.bullet_logger = true - Bullet.raise = false # raise an error if n+1 query occurs - end # Settings specified here will take precedence over those in config/application.rb. config.cache_classes = true diff --git a/config/initializers/touchpoints.rb b/config/initializers/touchpoints.rb index e2ffb4d83..d78ba6def 100644 --- a/config/initializers/touchpoints.rb +++ b/config/initializers/touchpoints.rb @@ -1 +1,2 @@ -APPROVED_DOMAINS = ['.gov', '.mil', '.edu'].freeze \ No newline at end of file +APPROVED_DOMAINS = ['.gov', '.mil', '.edu'].freeze +APPROVED_WEBSITE_DOMAINS = (APPROVED_DOMAINS + ['.org']).freeze \ No newline at end of file diff --git a/config/routes.rb b/config/routes.rb index 23e5571bc..0f9ffc498 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -145,6 +145,7 @@ resources :cx_collection_details do member do get 'upload', to: 'cx_collection_details#upload', as: :upload + post 'upload', to: 'cx_collection_details#upload_csv', as: :post_csv end end diff --git a/db/migrate/20231114205538_create_cx_collection_detail_uploads.rb b/db/migrate/20231114205538_create_cx_collection_detail_uploads.rb new file mode 100644 index 000000000..8360c733f --- /dev/null +++ b/db/migrate/20231114205538_create_cx_collection_detail_uploads.rb @@ -0,0 +1,12 @@ +class CreateCxCollectionDetailUploads < ActiveRecord::Migration[7.1] + def change + create_table :cx_collection_detail_uploads do |t| + t.integer :user_id + t.integer :cx_collection_detail_id + t.integer :size, comment: "file size of the s3 object" + t.string :key, comment: "s3 path to the asset" + + t.timestamps + end + end +end diff --git a/db/schema.rb b/db/schema.rb index 695ed061b..ce48be801 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema[7.1].define(version: 2023_11_02_184253) do +ActiveRecord::Schema[7.1].define(version: 2023_11_14_205538) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -187,6 +187,15 @@ t.datetime "updated_at", null: false end + create_table "cx_collection_detail_uploads", force: :cascade do |t| + t.integer "user_id" + t.integer "cx_collection_detail_id" + t.integer "size", comment: "file size of the s3 object" + t.string "key", comment: "s3 path to the asset" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + end + create_table "cx_collection_details", force: :cascade do |t| t.integer "cx_collection_id" t.integer "service_id" diff --git a/db/seeds.rb b/db/seeds.rb index ec20497ed..e3088ee6f 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -134,9 +134,6 @@ def production_suitable_seeds name: 'Example HISP', description: 'Description for an example HISP', notes: 'notes for example HISP', - department: 'Example Department', - department_abbreviation: 'dept', - bureau: 'Example Bureau', slug: 'example-service1', new: false, }) @@ -146,9 +143,6 @@ def production_suitable_seeds name: 'Example High Impact Service Provider - example.gov', description: 'A Description of the Example HISP', notes: 'notes on the example.gov HISP', - department: 'Example', - department_abbreviation: 'ex', - bureau: 'CX Labs', slug: 'example-service2', new: false, }) @@ -158,9 +152,6 @@ def production_suitable_seeds name: 'GSA High Impact Service Provider - USA.gov', description: 'A Description of the USA.gov HISP', notes: 'notes on the usa.gov HISP', - department: 'General Services Administration', - department_abbreviation: 'gsa', - bureau: 'Technology Transformation Services', slug: 'gsa-usagov', new: true, }) diff --git a/spec/features/admin/forms_spec.rb b/spec/features/admin/forms_spec.rb index afc260a94..46b996b89 100644 --- a/spec/features/admin/forms_spec.rb +++ b/spec/features/admin/forms_spec.rb @@ -1379,11 +1379,11 @@ before do visit questions_admin_form_path(form2) expect(page).to have_selector('.form-add-question', count: 2) - - find_all('.form-add-question').first.click + find("#form_section_1").find('.form-add-question').click fill_in 'question_text', with: 'Question in Form Section 1' select('text_field', from: 'question_question_type') click_on 'Update Question' + expect(page).to have_css(".usa-tag", text: "ANSWER_02") # Select the Add Question button in the 2nd Form Section visit questions_admin_form_path(form2) expect(find_all('.form-add-question').size).to eq(2) diff --git a/spec/features/admin/service_providers_spec.rb b/spec/features/admin/service_providers_spec.rb index 356f3482a..0c99b16d9 100644 --- a/spec/features/admin/service_providers_spec.rb +++ b/spec/features/admin/service_providers_spec.rb @@ -25,7 +25,7 @@ expect(page).to have_content('Service Providers') expect(page.current_path).to eq(admin_service_providers_path) expect(page).to have_content(service_provider.name) - expect(page).to have_content('Download as hisps.csv') + expect(page).to have_content('Download hisps.csv') end end diff --git a/spec/models/cx_collection_detail_upload_spec.rb b/spec/models/cx_collection_detail_upload_spec.rb new file mode 100644 index 000000000..93133d256 --- /dev/null +++ b/spec/models/cx_collection_detail_upload_spec.rb @@ -0,0 +1,5 @@ +require 'rails_helper' + +RSpec.describe CxCollectionDetailUpload, type: :model do + pending "add some examples to (or delete) #{__FILE__}" +end