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) %>
+
+
+
+ User
+ File path
+ Size
+ Timestamp
+
+
+
+
+
+ <% uploads.each do |upload| %>
+
+
+ <%= 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 %>
+
+
+ <% end %>
+
+
+
+
+
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 %>
<% 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? %>
+
+
+
+
+ Service
+ Transaction point
+ Channel
+
+
+
+ <% @cx_collection.cx_collection_details.order(:channel).each do |cx_collection| %>
+
+
+ <%= cx_collection.try(:service).try(:name) %>
+
+
+ <%= link_to cx_collection.transaction_point, admin_cx_collection_detail_path(cx_collection) %>
+
+
+ <%= cx_collection.channel %>
+
+
+ <% end %>
+
+
+
+ <%- 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 %>
-
+
-
- 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 @@
Disclaimer text
-
-
-
+
+
+
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 %>
- ">
+ <% if option.value == "effectiveness" %>
+ ">
+ <% elsif option.value == "efficiency" %>
+ ">
+ <% elsif option.value == "ease" %>
+ ">
+ <% elsif option.value == "transparency" %>
+ ">
+ <% else %>
+ ">
+ <% end %>
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