From 0ec9e4f7a7a4eedbff89458bb0e22adab1af5e83 Mon Sep 17 00:00:00 2001 From: Ryan Wold <64987852+ryanwoldatwork@users.noreply.github.com> Date: Wed, 10 May 2023 16:46:43 -0700 Subject: [PATCH] updates to registry screens * updates to open-api spec file * update DigitalServiceAccounts * add linktree to Service Accounts * show parent and child organizations on an Org * update gems * don't require federal register url for CX Data Collections --- Gemfile | 2 +- Gemfile.lock | 42 +- .../admin/digital_products_controller.rb | 8 +- .../digital_service_accounts_controller.rb | 8 +- app/models/digital_service_account.rb | 1 + app/models/organization.rb | 4 + .../digital_product_versions/index.html.erb | 2 +- .../admin/digital_products/_tags.html.erb | 14 +- .../admin/digital_products/add_tag.js.erb | 1 + .../admin/digital_products/review.html.erb | 2 + .../digital_service_accounts/_tags.html.erb | 18 +- .../digital_service_accounts/add_tag.js.erb | 1 + .../digital_service_accounts/review.html.erb | 2 + .../_form.html.erb | 2 +- app/views/admin/organizations/show.html.erb | 210 +++-- app/views/admin/services/show.html.erb | 5 +- public/api/v1/openapi.yml | 822 ++++++++++++++++-- .../admin/digital_service_accounts_spec.rb | 2 +- 18 files changed, 924 insertions(+), 222 deletions(-) diff --git a/Gemfile b/Gemfile index c01f075b9..89a2abc5e 100644 --- a/Gemfile +++ b/Gemfile @@ -97,7 +97,7 @@ group :test do gem 'factory_bot_rails' gem 'rails-controller-testing' gem 'rspec-rails' - gem 'selenium-webdriver' + gem 'selenium-webdriver', "4.8.6" gem 'simplecov', require: false gem 'webdrivers', '>= 5.1.0' end diff --git a/Gemfile.lock b/Gemfile.lock index f476b685e..e3ee7e627 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -96,10 +96,10 @@ GEM aes_key_wrap (1.1.0) ast (2.4.2) aws-eventstream (1.2.0) - aws-partitions (1.749.0) + aws-partitions (1.762.0) aws-record (2.10.1) aws-sdk-dynamodb (~> 1.18) - aws-sdk-core (3.171.0) + aws-sdk-core (3.172.0) aws-eventstream (~> 1, >= 1.0.2) aws-partitions (~> 1, >= 1.651.0) aws-sigv4 (~> 1.5) @@ -220,12 +220,12 @@ GEM activesupport (>= 5.0) hashie (5.0.0) httpclient (2.8.3) - i18n (1.12.0) + i18n (1.13.0) concurrent-ruby (~> 1.0) image_processing (1.12.2) mini_magick (>= 4.9.5, < 5) ruby-vips (>= 2.0.17, < 3) - importmap-rails (1.1.5) + importmap-rails (1.1.6) actionpack (>= 6.0.0) railties (>= 6.0.0) jbuilder (2.11.5) @@ -262,7 +262,7 @@ GEM rb-fsevent (~> 0.10, >= 0.10.3) rb-inotify (~> 0.9, >= 0.9.10) logstop (0.3.0) - loofah (2.20.0) + loofah (2.21.1) crass (~> 1.0.2) nokogiri (>= 1.5.9) mail (2.8.1) @@ -278,7 +278,7 @@ GEM mime-types-data (3.2023.0218.1) mini_magick (4.12.0) mini_mime (1.1.2) - mini_portile2 (2.8.1) + mini_portile2 (2.8.2) minitest (5.18.0) msgpack (1.7.0) multi_json (1.15.0) @@ -293,7 +293,7 @@ GEM timeout net-smtp (0.3.3) net-protocol - newrelic_rpm (9.2.0) + newrelic_rpm (9.2.2) nio4r (2.5.9) nokogiri (1.14.3) mini_portile2 (~> 2.8.0) @@ -322,9 +322,9 @@ GEM activerecord (>= 5.2) request_store (~> 1.1) parallel (1.23.0) - parser (3.2.2.0) + parser (3.2.2.1) ast (~> 2.4.1) - pg (1.4.6) + pg (1.5.3) pry (0.14.2) coderay (~> 1.1) method_source (~> 1.0) @@ -332,10 +332,10 @@ GEM puma (5.6.5) nio4r (~> 2.0) racc (1.6.2) - rack (2.2.6.4) + rack (2.2.7) rack-cors (1.1.1) rack (>= 2.0.0) - rack-protection (3.0.5) + rack-protection (3.0.6) rack rack-test (2.1.0) rack (>= 1.3) @@ -390,22 +390,22 @@ GEM railties (>= 5.2) rexml (3.2.5) rolify (6.0.1) - rspec-core (3.12.1) + rspec-core (3.12.2) rspec-support (~> 3.12.0) - rspec-expectations (3.12.2) + rspec-expectations (3.12.3) diff-lcs (>= 1.2.0, < 2.0) rspec-support (~> 3.12.0) rspec-mocks (3.12.5) diff-lcs (>= 1.2.0, < 2.0) rspec-support (~> 3.12.0) - rspec-rails (6.0.1) + rspec-rails (6.0.2) actionpack (>= 6.1) activesupport (>= 6.1) railties (>= 6.1) - rspec-core (~> 3.11) - rspec-expectations (~> 3.11) - rspec-mocks (~> 3.11) - rspec-support (~> 3.11) + rspec-core (~> 3.12) + rspec-expectations (~> 3.12) + rspec-mocks (~> 3.12) + rspec-support (~> 3.12) rspec-support (3.12.0) rspec_junit_formatter (0.6.0) rspec-core (>= 2, < 4, != 2.12.0) @@ -419,7 +419,7 @@ GEM rubocop-ast (>= 1.28.0, < 2.0) ruby-progressbar (~> 1.7) unicode-display_width (>= 2.4.0, < 3.0) - rubocop-ast (1.28.0) + rubocop-ast (1.28.1) parser (>= 3.2.1.0) rubocop-capybara (2.17.1) rubocop (~> 1.41) @@ -504,7 +504,7 @@ GEM chronic (>= 0.6.3) xpath (3.2.0) nokogiri (~> 1.8) - zeitwerk (2.6.7) + zeitwerk (2.6.8) PLATFORMS ruby @@ -560,7 +560,7 @@ DEPENDENCIES rubocop-rails rubocop-rspec sass-rails (>= 6.0.0) - selenium-webdriver + selenium-webdriver (= 4.8.6) sidekiq simplecov sprockets-rails diff --git a/app/controllers/admin/digital_products_controller.rb b/app/controllers/admin/digital_products_controller.rb index 1fee91d97..ab58ad8a4 100644 --- a/app/controllers/admin/digital_products_controller.rb +++ b/app/controllers/admin/digital_products_controller.rb @@ -61,7 +61,9 @@ def edit def create @digital_product = DigitalProduct.new(digital_product_params) - @digital_product.organization_list.add(current_user.organization_id) + organization = current_user.organization + @digital_product.organization_list.add(organization.id) + @digital_product.organization_list.add(organization.parent.id) if organization.parent if @digital_product.save Event.log_event(Event.names[:digital_product_created], 'Digital Product', @digital_product.id, "Digital Product #{@digital_product.name} created at #{DateTime.now}", current_user.id) @@ -111,7 +113,9 @@ def remove_tag def add_organization ensure_digital_product_permissions(digital_product: @digital_product) - @digital_product.organization_list.add(params[:organization_id]) + organization = Organization.find(params[:organization_id]) + @digital_product.organization_list.add(organization.id) + @digital_product.organization_list.add(organization.parent.id) if organization.parent @digital_product.save set_sponsoring_agency_options end diff --git a/app/controllers/admin/digital_service_accounts_controller.rb b/app/controllers/admin/digital_service_accounts_controller.rb index 6cd049f32..7666bc10a 100644 --- a/app/controllers/admin/digital_service_accounts_controller.rb +++ b/app/controllers/admin/digital_service_accounts_controller.rb @@ -69,7 +69,9 @@ def edit def create @digital_service_account = DigitalServiceAccount.new(digital_service_account_params) - @digital_service_account.organization_list.add(current_user.organization_id) + organization = Organization.find(current_user.organization_id) + @digital_service_account.organization_list.add(organization.id) + @digital_service_account.organization_list.add(organization.parent.id) if organization.parent if @digital_service_account.save current_user.add_role(:contact, @digital_service_account) @@ -131,7 +133,9 @@ def remove_tag def add_organization ensure_digital_service_account_permissions(digital_service_account: @digital_service_account) - @digital_service_account.organization_list.add(params[:organization_id]) + organization = Organization.find(params[:organization_id]) + @digital_service_account.organization_list.add(organization.id) + @digital_service_account.organization_list.add(organization.parent.id) if organization.parent @digital_service_account.save set_sponsoring_agency_options end diff --git a/app/models/digital_service_account.rb b/app/models/digital_service_account.rb index 49aa929d0..3d352b88c 100644 --- a/app/models/digital_service_account.rb +++ b/app/models/digital_service_account.rb @@ -65,6 +65,7 @@ def self.list 'Ideascale', 'Instagram', 'Linkedin', + 'Linktree', 'Livestream', 'Mastodon', 'Medium', diff --git a/app/models/organization.rb b/app/models/organization.rb index 9e5c2cdc9..0e585f29f 100644 --- a/app/models/organization.rb +++ b/app/models/organization.rb @@ -25,6 +25,10 @@ class Organization < ApplicationRecord def parent parent_id ? Organization.find(parent_id) : nil end + + def children + Organization.where(parent_id: self.id) + end def slug abbreviation.downcase diff --git a/app/views/admin/digital_product_versions/index.html.erb b/app/views/admin/digital_product_versions/index.html.erb index 2c11a9f82..3dc0ff345 100644 --- a/app/views/admin/digital_product_versions/index.html.erb +++ b/app/views/admin/digital_product_versions/index.html.erb @@ -12,7 +12,7 @@ </div> <% if digital_product_permissions?(digital_product: @digital_product, user: current_user) %> - <%= link_to "New digital product version", new_admin_digital_product_digital_product_version_path(@digital_product), class: "usa-button" %> + <%= link_to "New digital product version", new_admin_digital_product_digital_product_version_path(@digital_product), class: "usa-button full-width" %> <% end %> <table class="usa-table width-full"> diff --git a/app/views/admin/digital_products/_tags.html.erb b/app/views/admin/digital_products/_tags.html.erb index 56e71ec77..045f47914 100644 --- a/app/views/admin/digital_products/_tags.html.erb +++ b/app/views/admin/digital_products/_tags.html.erb @@ -4,7 +4,16 @@ <%= label_tag :tags, nil, class: "usa-label" %> <% if digital_product_permissions?(digital_product: digital_product, user: current_user) %> - <%= f.text_field :tag_list, placeholder: "Add a tag" , value: nil, class: "usa-input tag-input" %> + <ul class="usa-button-group"> + <li class="usa-button-group__item"> + <%= f.text_field :tag_list, placeholder: "Add a tag" , value: nil, class: "usa-input tag-input margin-top-0" %> + </li> + <li class="usa-button-group__item"> + <%= f.button id: "tag_list_add_button", class: "usa-button", style: "display: inline;", "aria-label" => "Add tag" do %> + <span class="fa fa-plus"></span> + <% end %> + </li> + </ul> <% end %> <div class="tag-list"> @@ -32,7 +41,7 @@ <script> $(function() { - $(".tag-input").on("blur", function(event) { + $("#tag_list_add_button").on("click", function(event) { event.preventDefault(); var thisForm = $(this).closest("form"); @@ -43,7 +52,6 @@ }).done(function(data) { event.target.focus(); }); - }); // return on Enter diff --git a/app/views/admin/digital_products/add_tag.js.erb b/app/views/admin/digital_products/add_tag.js.erb index d309e5622..a78b6ab45 100644 --- a/app/views/admin/digital_products/add_tag.js.erb +++ b/app/views/admin/digital_products/add_tag.js.erb @@ -1 +1,2 @@ $(".tags-div").html("<%= escape_javascript render(partial: 'admin/digital_products/tags', locals: { digital_product: @digital_product }) %>"); +$("#digital_product_tag_list").focus() diff --git a/app/views/admin/digital_products/review.html.erb b/app/views/admin/digital_products/review.html.erb index 237765e35..403b6da5d 100644 --- a/app/views/admin/digital_products/review.html.erb +++ b/app/views/admin/digital_products/review.html.erb @@ -26,6 +26,7 @@ <tr> <th data-sortable scope="col">Organization</th> <th data-sortable scope="col">Name</th> + <th data-sortable scope="col">Contacts</th> <th data-sortable scope="col">Status</th> </tr> </thead> @@ -35,6 +36,7 @@ <tr> <td><%= link_to digital_product.name, admin_digital_product_path(digital_product) %></td> <td><%= digital_product.name %></td> + <td><%= digital_product.contacts.collect(&:email).join(", ") %></td> <td><%= digital_product.aasm_state %></td> </tr> <% end %> diff --git a/app/views/admin/digital_service_accounts/_tags.html.erb b/app/views/admin/digital_service_accounts/_tags.html.erb index e79db594c..3a7b3cade 100644 --- a/app/views/admin/digital_service_accounts/_tags.html.erb +++ b/app/views/admin/digital_service_accounts/_tags.html.erb @@ -3,8 +3,17 @@ <div class="grid-col-6"> <%= label_tag "Tags", nil, class: "usa-label" %> - <% if digital_service_account_permissions?(digital_service_account: @digital_service_account, user: current_user) %> - <%= f.text_field :tag_list, placeholder: "Add a tag" , value: nil, class: "usa-input tag-input" %> + <% if digital_service_account_permissions?(digital_service_account: @digital_service_account, user: current_user) %> + <ul class="usa-button-group"> + <li class="usa-button-group__item"> + <%= f.text_field :tag_list, placeholder: "Add a tag" , value: nil, class: "usa-input tag-input margin-top-0" %> + </li> + <li class="usa-button-group__item"> + <%= f.button id: "tag_list_add_button", class: "usa-button", style: "display: inline;", "aria-label" => "Add tag" do %> + <span class="fa fa-plus"></span> + <% end %> + </li> + </ul> <% end %> <div class="tag-list margin-top-1"> @@ -31,7 +40,7 @@ <% if digital_service_account_permissions?(digital_service_account: @digital_service_account, user: current_user) %> <script> $(function() { - $(".tag-input").on("blur", function(event) { + $("#tag_list_add_button").on("click", function(event) { event.preventDefault(); var thisForm = $(this).closest("form"); $.ajax({ @@ -41,6 +50,7 @@ }); }); + // return on Enter $(".tag-input").on("keypress", function (e) { if (e.which == 13) { document.activeElement.blur(); @@ -48,7 +58,7 @@ } }); - $(".remove-tag-link").on("click", function(e) { + $(".tag-list .remove-tag-link").on("click", function(e) { event.preventDefault(); var thisForm = $(this).closest("form"); $.ajax({ diff --git a/app/views/admin/digital_service_accounts/add_tag.js.erb b/app/views/admin/digital_service_accounts/add_tag.js.erb index ff68bdc14..9398bb662 100644 --- a/app/views/admin/digital_service_accounts/add_tag.js.erb +++ b/app/views/admin/digital_service_accounts/add_tag.js.erb @@ -1 +1,2 @@ $(".tags-div").html("<%= escape_javascript render(partial: 'admin/digital_service_accounts/tags', locals: { digital_service_account: @digital_service_account }) %>"); +$("#digital_service_account_tag_list").focus() diff --git a/app/views/admin/digital_service_accounts/review.html.erb b/app/views/admin/digital_service_accounts/review.html.erb index 5a3f00c61..d4fe78fc6 100644 --- a/app/views/admin/digital_service_accounts/review.html.erb +++ b/app/views/admin/digital_service_accounts/review.html.erb @@ -26,6 +26,7 @@ <tr> <th data-sortable scope="col">Platform</th> <th data-sortable scope="col">Account name</th> + <th data-sortable scope="col">Contacts</th> <th data-sortable scope="col">Status</th> </tr> </thead> @@ -41,6 +42,7 @@ <% end %> </td> <td><%= digital_service_account.name %></td> + <td><%= digital_service_account.contacts.collect(&:email).join(", ") %></td> <td><%= digital_service_account.aasm_state %></td> </tr> <% end %> diff --git a/app/views/admin/omb_cx_reporting_collections/_form.html.erb b/app/views/admin/omb_cx_reporting_collections/_form.html.erb index e9927b771..28b667c56 100644 --- a/app/views/admin/omb_cx_reporting_collections/_form.html.erb +++ b/app/views/admin/omb_cx_reporting_collections/_form.html.erb @@ -67,7 +67,7 @@ <p class="font-sans-2xs text-muted"> Enter the <a href="https://www.reginfo.gov/" target="_blank">reginfo.gov</a> URL for the survey form. </p> - <%= form.url_field :federal_register_url, class: "usa-input", placeholder: "https://www.reginfo.gov/...", required: true %> + <%= form.url_field :federal_register_url, class: "usa-input", placeholder: "https://www.reginfo.gov/..." %> </div> <div class="field"> <%= form.label :operational_metrics, class: "usa-label" %> diff --git a/app/views/admin/organizations/show.html.erb b/app/views/admin/organizations/show.html.erb index 8d63bd479..5c3e1b8ae 100644 --- a/app/views/admin/organizations/show.html.erb +++ b/app/views/admin/organizations/show.html.erb @@ -15,110 +15,132 @@ <div class="grid-row"> <div class="grid-col-8"> - <div> - <div class="grid-row"> - <% if @organization.cfo_act_agency? %> - <div class="grid-col-12"> - <span class="usa-tag bg-success"> - CFO Act Agency - </span> - </div> - <% end -%> + <div class="grid-row"> + <% if @organization.cfo_act_agency? %> + <div class="grid-col-12"> + <span class="usa-tag bg-success"> + CFO Act Agency + </span> + </div> + <% end -%> - <div class="grid-col-12"> - <%= label_tag "Name", nil, class: "usa-label" %> - <%= @organization.name %> - </div> - <% if @organization.parent %> - <div class="grid-col-12"> - <%= label_tag "Parent Organization name", nil, class: "usa-label" %> - <%= @organization.parent.name %> - </div> - <% end %> - <div class="grid-col-12"> - <%= label_tag "Abbreviation", nil, class: "usa-label" %> - <%= @organization.abbreviation %> - </div> - <div class="grid-col-12"> - <div> - <%= label_tag "Organization Domain", nil, class: "usa-label" %> - <small> - used for the Allowlist of users email addresses - </small> - <br> - <br> - <%= @organization.domain %> - </div> - </div> - <div class="grid-col-12"> - <%= label_tag "Website URL", nil, class: "usa-label" %> + <% if @organization.parent %> + <div class="grid-col-12"> + <%= label_tag "Parent Organization name", nil, class: "usa-label" %> + <%= link_to @organization.parent.name, admin_organization_path(@organization.parent) %> + </div> + <% end -%> + + <div class="grid-col-12"> + <%= label_tag "Name", nil, class: "usa-label" %> + <%= @organization.name %> + </div> + <div class="grid-col-12"> + <%= label_tag "Abbreviation", nil, class: "usa-label" %> + <%= @organization.abbreviation %> + </div> + <div class="grid-col-12"> + <div> + <%= label_tag "Organization Domain", nil, class: "usa-label" %> + <small> + used for the Allowlist of users email addresses + </small> <br> - <%= link_to(@organization.url, @organization.url, target: "_blank", rel: "noopener") %> + <br> + <%= @organization.domain %> </div> </div> - - - <div class="usa-prose"> - <%= label_tag "Mission statement", nil, class: "usa-label" %> + <div class="grid-col-12"> + <%= label_tag "Website URL", nil, class: "usa-label" %> <br> - <% if @organization.mission_statement.present? %> - <%= @organization.mission_statement %> - <% else %> - <div class="usa-alert usa-alert--info"> - <div class="usa-alert__body"> - <p class="usa-alert__text"> - Mission statement has not been entered - </p> - </div> + <%= link_to(@organization.url, @organization.url, target: "_blank", rel: "noopener") %> + </div> + </div> + + <div class="usa-prose"> + <%= label_tag "Mission statement", nil, class: "usa-label" %> + <br> + <% if @organization.mission_statement.present? %> + <%= @organization.mission_statement %> + <% else %> + <div class="usa-alert usa-alert--info"> + <div class="usa-alert__body"> + <p class="usa-alert__text"> + Mission statement has not been entered + </p> + </div> + </div> + <% end -%> + </div> + <% if @organization.logo %> + <p> + <%= label_tag "Logo", nil, class: "usa-label" %> + <br> + <% if @organization.logo_url.present? %> + (displaying Thumbnail version) + <br> + <br> + <%= image_tag(@organization.logo.thumb.url) %> + <br> + <%= link_to "Full Size", @organization.logo.url, target: "_blank", rel: "noopener" %><br> + <%= link_to "Thumbnail Size", @organization.logo.thumb.url, target: "_blank", rel: "noopener" %><br> + <%= link_to "Card Size", @organization.logo.card.url, target: "_blank", rel: "noopener" %><br> + <% else %> + A logo has not yet been uploaded + <% end %> + </p> + <% end -%> + <p> + <%= label_tag "Digital Analytics URL", nil, class: "usa-label" %> + <% if @organization.digital_analytics_path? %> + <%= link_to("https://analytics.usa.gov/#{@organization.digital_analytics_path}", "https://analytics.usa.gov/#{@organization.digital_analytics_path}", target: "_blank", rel: "noopener") %> + <% else %> + <div class="usa-alert usa-alert--info"> + <div class="usa-alert__body"> + <p class="usa-alert__text"> + DAP path has not been entered + </p> </div> - <% end -%> </div> - <% if @organization.logo %> - <p> - <%= label_tag "Logo", nil, class: "usa-label" %> - <br> - <% if @organization.logo_url.present? %> - (displaying Thumbnail version) - <br> - <br> - <%= image_tag(@organization.logo.thumb.url) %> - <br> - <%= link_to "Full Size", @organization.logo.url, target: "_blank", rel: "noopener" %><br> - <%= link_to "Thumbnail Size", @organization.logo.thumb.url, target: "_blank", rel: "noopener" %><br> - <%= link_to "Card Size", @organization.logo.card.url, target: "_blank", rel: "noopener" %><br> - <% else %> - A logo has not yet been uploaded - <% end %> - </p> <% end -%> - <p> - <%= label_tag "Digital Analytics URL", nil, class: "usa-label" %> - <% if @organization.digital_analytics_path? %> - <%= link_to("https://analytics.usa.gov/#{@organization.digital_analytics_path}", "https://analytics.usa.gov/#{@organization.digital_analytics_path}", target: "_blank", rel: "noopener") %> - <% else %> - <div class="usa-alert usa-alert--info"> - <div class="usa-alert__body"> - <p class="usa-alert__text"> - DAP path has not been entered - </p> - </div> + </p> + <p> + <%= label_tag "Notes", nil, class: "usa-label" %> + <% if @organization.notes.present? %> + <%= @organization.notes %> + <% else %> + <div class="usa-alert usa-alert--info"> + <div class="usa-alert__body"> + <p class="usa-alert__text"> + Notes have not been entered + </p> </div> - <% end -%> - </p> - <p> - <%= label_tag "Notes", nil, class: "usa-label" %> - <% if @organization.notes.present? %> - <%= @organization.notes %> - <% else %> - <div class="usa-alert usa-alert--info"> - <div class="usa-alert__body"> - <p class="usa-alert__text"> - Notes have not been entered - </p> - </div> + </div> + <% end -%> + </p> + + <div class="sub-organizations well"> + <h3> + <%= pluralize(@organization.children.size, "Sub-agency") %> + </h3> + + <% if @organization.children.present? %> + <ul class="usa-list"> + <% @organization.children.order(:name).each do |organization| %> + <li> + <%= link_to organization.name, admin_organization_path(organization) %> + </li> + <% end %> + </ul> + <% else %> + <div class="usa-alert usa-alert--info"> + <div class="usa-alert__body"> + <p class="usa-alert__text"> + No Sub-agencies at this time + </p> </div> - <% end -%> - </p> + </div> + <% end %> </div> <% if admin_permissions? || current_user.organization == @organization %> diff --git a/app/views/admin/services/show.html.erb b/app/views/admin/services/show.html.erb index 821465ed2..ce8084394 100644 --- a/app/views/admin/services/show.html.erb +++ b/app/views/admin/services/show.html.erb @@ -72,7 +72,10 @@ <p> <strong>Service type</strong> <br> - <%= @service.kind %> + <% @service.kind.each do |i| %> + <%= i %> + <br> + <% end if @service.kind.present? %> </p> <div class="well"> diff --git a/public/api/v1/openapi.yml b/public/api/v1/openapi.yml index fb339b085..27765af3d 100644 --- a/public/api/v1/openapi.yml +++ b/public/api/v1/openapi.yml @@ -1,14 +1,14 @@ openapi: 3.0.1 info: - description: The Touchpoints API allows agencys users to programatically read Forms and Responses. + description: The Touchpoints API enables users to read Forms, Responses, and other Customer Experience data. version: 1.0.0 title: Touchpoints API contact: name: Touchpoints - url: 'https://touchpoints.digital.gov' + url: 'https://touchpoints.digital.gov/' email: feedback-analytics@gsa.gov servers: - - url: 'https://api.data.gov/analytics/touchpoints/v1/' + - url: 'https://api.gsa.gov/analytics/touchpoints/v1/' variables: scheme: description: API responses are available via https only @@ -19,7 +19,7 @@ - name: TP description: Touchpoints paths: - /forms: + /forms.json: get: summary: List available data sets operationId: forms @@ -37,7 +37,7 @@ type: array items: $ref: '#/components/schemas/Form' - '/forms/{id}/': + '/forms/{id}.json': summary: Provides the general information about the API and the list of fields that can be used to query the dataset. description: This GET API returns the list of all the searchable field names that are in the oa_citations. Please see the 'fields' attribute which returns an array of field names. Each field or a combination of fields can be searched using the syntax options shown below. get: @@ -54,6 +54,47 @@ responses: '200': description: The dataset API for the given version is found and it is accessible to consume. + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/Form' + /websites.json: + get: + summary: List published websites + operationId: websites + tags: + - websites + responses: + '200': + description: Returns an array of websites + content: + application/json: + schema: + type: object + properties: + data: + type: array + items: + $ref: '#/components/schemas/Website' + '/websites/{id}.json': + summary: returns one website record + description: returns one website record + get: + operationId: websites#show + tags: + - websites + parameters: + - in: path + name: id + description: ID of the website + required: true + schema: + type: string + responses: + '200': + description: Returns one form content: application/json: schema: @@ -61,14 +102,93 @@ properties: data: type: object - properties: - id: - type: string - type: - type: string - attributes: - type: object - $ref: '#/components/schemas/Form' + $ref: '#/components/schemas/Website' + /digital_products.json: + get: + summary: List published digital products (Mobile Apps) + operationId: digital_products + tags: + - digital_products + responses: + '200': + description: Returns an array of digital_products + content: + application/json: + schema: + type: object + properties: + data: + type: array + items: + $ref: '#/components/schemas/DigitalProduct' + '/digital_products/{id}.json': + summary: returns one digital product record + description: returns one digital product record + get: + operationId: digital_products#show + tags: + - digital_products + parameters: + - in: path + name: id + description: ID of the digital product + required: true + schema: + type: string + responses: + '200': + description: Returns one digital product + content: + application/json: + schema: + type: object + properties: + data: + type: object + $ref: '#/components/schemas/DigitalProduct' + /digital_service_accounts.json: + get: + summary: List published digital service accounts (Social Media Accounts) + operationId: digital_service_accounts + tags: + - digital_service_accounts + responses: + '200': + description: Returns an array of digital_service_accounts + content: + application/json: + schema: + type: object + properties: + data: + type: array + items: + $ref: '#/components/schemas/DigitalServiceAccount' + '/digital_service_accounts/{id}.json': + summary: returns one digital service account record + description: returns one digital service account record + get: + operationId: digital_service_accounts#show + tags: + - digital_service_accounts + parameters: + - in: path + name: id + description: ID of the digital service account + required: true + schema: + type: string + responses: + '200': + description: Returns one digital service account + content: + application/json: + schema: + type: object + properties: + data: + type: object + $ref: '#/components/schemas/DigitalServiceAccount' components: securitySchemes: ApiKeyAuth: @@ -76,89 +196,236 @@ in: header name: X-API-KEY schemas: + Channel: + required: + - "id" + - "name" + - "created_at" + - "updated_at" + properties: + id: + type: "number" + example: 39 + name: + type: "string" + example: "website" + created_at: + type: "string" + example: "2022-01-20T20:44:35.603Z" + updated_at: + type: "string" + example: "2022-01-20T20:44:35.603Z" Form: type: object required: - id - name - properties: - id: - type: integer - format: int32 - type: - type: string - attributes: - type: object - properties: - uuid: - type: string - format: uuid - organization_id: - type: integer - format: int32 - name: - type: string - instructions: - type: string - kind: - type: string - notes: - type: string - status: - type: string - created_at: - type: string - updated_at: - type: string - element_selector: - type: string - whitelist_url: - type: string - whitelist_test_url: - type: string - display_header_logo: - type: boolean - display_header_square_logo: - type: boolean - early_submission: - type: boolean - template: - type: boolean - load_css: - type: boolean - logo: - type: object - success_text: - type: string - modal_button_text: - type: string - omb_approval_number: - type: string - expiration_date: - type: string - federal_register_url: - type: string - service_name: - type: string - survey_instrument_reference: - type: string - survey_form_activations: - type: integer - format: int32 - anticipated_delivery_count: - type: integer - format: int32 - relationships: - type: object - properties: - submissions: - type: object - properties: - data: - type: array - items: - $ref: '#/components/schemas/Submission' - + properties: + id: + type: "string" + type: + type: "string" + attributes: + required: + - "page" + - "size" + - "start_date" + - "end_date" + - "name" + - "title" + - "instructions" + - "disclaimer_text" + - "kind" + - "notes" + - "status" + - "created_at" + - "updated_at" + - "whitelist_url" + - "whitelist_test_url" + - "display_header_logo" + - "success_text_heading" + - "success_text" + - "modal_button_text" + - "display_header_square_logo" + - "early_submission" + - "user_id" + - "template" + - "uuid" + - "short_uuid" + - "organization_id" + - "omb_approval_number" + - "expiration_date" + - "medium" + - "federal_register_url" + - "anticipated_delivery_count" + - "service_name" + - "data_submission_comment" + - "survey_instrument_reference" + - "agency_poc_email" + - "agency_poc_name" + - "department" + - "bureau" + - "notification_emails" + - "aasm_state" + - "delivery_method" + - "element_selector" + - "survey_form_activations" + - "load_css" + - "logo" + - "time_zone" + - "response_count" + - "last_response_created_at" + properties: + page: + type: "number" + size: + type: "number" + start_date: + type: "string" + end_date: + type: "string" + name: + type: "string" + title: + type: "string" + instructions: + type: "string" + disclaimer_text: + type: "string" + kind: + type: "string" + notes: + type: "string" + created_at: + type: "string" + updated_at: + type: "string" + whitelist_url: + type: "string" + whitelist_test_url: + type: "string" + display_header_logo: + type: "boolean" + success_text_heading: + type: "string" + success_text: + type: "string" + modal_button_text: + type: "string" + display_header_square_logo: + type: "boolean" + early_submission: + type: "boolean" + user_id: + type: "number" + template: + type: "boolean" + uuid: + type: "string" + short_uuid: + type: "string" + organization_id: + type: "number" + omb_approval_number: + type: "string" + medium: + type: "string" + federal_register_url: + type: "string" + service_name: + type: "string" + survey_instrument_reference: + type: "string" + agency_poc_email: + type: "string" + agency_poc_name: + type: "string" + department: + type: "string" + bureau: + type: "string" + notification_emails: + type: "string" + aasm_state: + type: "string" + delivery_method: + type: "string" + element_selector: + type: "string" + survey_form_activations: + type: "number" + load_css: + type: "boolean" + logo: + required: + - "url" + - "thumb" + - "card" + - "tag" + - "logo_square" + properties: + url: + type: "string" + thumb: + required: + - "url" + properties: + url: + type: "string" + type: "object" + card: + required: + - "url" + properties: + url: + type: "string" + type: "object" + tag: + required: + - "url" + properties: + url: + type: "string" + type: "object" + logo_square: + required: + - "url" + properties: + url: + type: "string" + type: "object" + type: "object" + time_zone: + type: "string" + response_count: + type: "number" + last_response_created_at: + type: "string" + type: "object" + relationships: + type: "object" + required: + - "questions" + - "submissions" + properties: + questions: + type: "object" + required: + - "data" + properties: + data: + type: "array" + items: + $ref: '#/components/schemas/Question' + submissions: + type: "object" + required: + - "data" + properties: + data: + type: "array" + items: + $ref: '#/components/schemas/Submission' Forms: type: array items: @@ -232,7 +499,380 @@ type: boolean language: type: string + Question: + type: object + required: + - "data" + properties: + data: + type: "array" + items: + type: "object" + properties: + id: + type: "number" + form_id: + type: "number" + text: + type: "string" + question_type: + type: "string" + answer_field: + type: "string" + position: + type: "number" + is_required: + type: "boolean" + created_at: + type: "string" + updated_at: + type: "string" + form_section_id: + type: "number" Submissions: type: array items: $ref: '#/components/schemas/Submission' + Organization: + type: object + required: + - id + - name + - abbreviation + - domain + properties: + id: + type: "number" + name: + type: "string" + url: + type: "string" + abbreviation: + type: "string" + domain: + type: "string" + logo: + required: + - "url" + - "thumb" + - "card" + - "tag" + - "logo_square" + properties: + thumb: + required: + - "url" + properties: {} + type: "object" + card: + required: + - "url" + properties: {} + type: "object" + tag: + required: + - "url" + properties: {} + type: "object" + logo_square: + required: + - "url" + properties: {} + type: "object" + type: object + digital_analytics_path: + type: "string" + mission_statement: + type: "string" + mission_statement_url: + type: "string" + performance_url: + type: "string" + strategic_plan_url: + type: "string" + learning_agenda_url: + type: "string" + cfo_act_agency: + type: "boolean" + PublicUser: + type: object + properties: + email: + type: "string" + Service: + required: + - "data" + properties: + data: + type: "array" + items: + type: "object" + properties: + id: + type: "string" + type: + type: "string" + attributes: + required: + - "name" + - "description" + - "organization_id" + - "organization_abbreviation" + - "organization_name" + - "service_provider_id" + - "service_provider_name" + - "justification_text" + - "kind" + - "transactional" + - "notes" + - "hisp" + - "department" + - "bureau" + - "service_abbreviation" + - "service_slug" + - "service_owner_email" + - "service_managers" + - "url" + - "homepage_url" + - "channels" + - "tags" + - "available_in_person" + - "available_digitally" + - "available_via_phone" + properties: + name: + type: "string" + description: + type: "string" + organization_id: + type: "number" + organization_abbreviation: + type: "string" + organization_name: + type: "string" + service_provider_id: + type: "number" + service_provider_name: + type: "string" + justification_text: + type: "string" + kind: + type: "array" + items: + type: "string" + transactional: + type: "boolean" + notes: + type: "string" + hisp: + type: "boolean" + department: + type: "string" + bureau: + type: "string" + service_abbreviation: + type: "string" + service_slug: + type: "string" + service_owner_email: + type: "string" + service_managers: + type: "array" + items: + type: "object" + properties: + email: + type: "string" + url: + type: "string" + homepage_url: + type: "string" + channels: + type: "array" + items: + type: "object" + properties: + id: + type: "number" + name: + type: "string" + created_at: + type: "string" + updated_at: + type: "string" + taggings_count: + type: "number" + tags: + type: "array" + items: + $ref: '#/components/schemas/Tag' + available_in_person: + type: "boolean" + available_digitally: + type: "boolean" + available_via_phone: + type: "boolean" + Tag: + required: + - "id" + - "name" + - "created_at" + - "updated_at" + properties: + id: + type: "number" + example: 1776 + name: + type: "string" + example: "customer-experience" + created_at: + type: "string" + example: "2022-01-12T17:43:09.569Z" + updated_at: + type: "string" + example: "2022-01-12T17:43:09.569Z" + Website: + type: object + Websites: + type: array + items: + $ref: '#/components/schemas/Website' + DigitalProduct: + required: + - "data" + - "links" + - "meta" + properties: + data: + type: "array" + items: + type: "object" + properties: + id: + type: "string" + example: "8" + type: + type: "string" + example: "digital_products" + attributes: + type: object + required: + - "agencies" + - "contacts" + - "service" + - "url" + - "code_repository_url" + - "language" + - "status" + - "short_description" + - "long_description" + - "tags" + properties: + agencies: + type: "array" + items: + $ref: '#/components/schemas/Organization' + example: [] + contacts: + type: "array" + items: + $ref: '#/components/schemas/PublicUser' + example: [] + language: + type: "string" + example: "English" + status: + type: "string" + example: "published" + short_description: + type: "string" + example: "Explore many of the most cherished cultural and historical sites on the National Mall." + long_description: + type: "string" + example: "<p>This is the official National Park Service app for the National Mall and Memorial Parks. On your next visit to Washington, D.C., use it to explore many of the most cherished cultural and historical sites in the United States—from the Lincoln Memorial to the White House. The app includes a total of 70 sites.</p><p><strong>Features:</strong></p><p><strong>Map</strong> – Official National Park Service map of the central tourist area in Washington, D.C. Easy to use while outdoors, the map features large font sizes, walkways that are easily distinguishable from roads, and three zoom levels. By tapping the “Locate me” icon you will always know where you are.</p><p><strong>Park Lens</strong> – Find out what is around you with augmented reality. Just hold up your device and look through the camera. Labels will appear identifying all sites on the National Mall.</p><p><strong>Walking directions</strong> – Get from one place to another by following a line on the map or a list of directions. Estimated walking times are given.</p><p><strong>Sites</strong> – Learn more about points of interest with lively text, professional photographs, and engaging podcasts under the “Album” button. The “Info” button includes the site’s location, hours of operation, nearest Metro station, and other essential information.</p><p><strong>Tours</strong> – Follow a recommended tour depending on how much time you have or your special interest—from memorials to presidents to military monuments to destinations off the beaten path. You can even create personal tours with the “My Tour” feature—just tap the “+” at the bottom right of a site page. The app maps the route for you.</p><p><strong>Events and News</strong> – Get up-to-date information from the National Park Service about what is happening at the National Mall and Memorial Parks.</p><p><strong>Postcard</strong> – Send a digital postcard to friends and family from the National Mall with the tap of a button.</p><p><strong>Accessibility</strong> – Audio described images combined with the built-in iOS accessibility features will let all people enjoy the National Mall and Memorial Parks.</p><p><strong>Park Partner</strong> – The Trust for the National Mall strives to make the National Mall the best park in the world. Learn more about the essential assistance this organization provides.</p><p><strong>Small size</strong> – Weighing in at 13.7MB, the app will download relatively quickly via a 3G cellular connection or the free Wi-Fi available on the east end the National Mall.</p>" + tags: + type: "array" + items: + $ref: '#/components/schemas/Tag' + example: [] + links: + required: + - "first" + - "last" + properties: + first: + type: "string" + example: "https://touchpoints.app.cloud.gov/api/v1/digital_products.json?API_KEY=1234&page=1" + last: + type: "string" + example: "https://touchpoints.app.cloud.gov/api/v1/digital_products.json?API_KEY=1234&page=9" + type: "object" + meta: + required: + - "size" + - "page" + - "totalPages" + properties: + size: + type: "number" + example: 100 + page: + type: "number" + example: 0 + totalPages: + type: "number" + example: 1 + type: "object" + + DigitalProducts: + type: array + items: + $ref: '#/components/schemas/DigitalProduct' + DigitalServiceAccount: + type: object + properties: + name: + type: "string" + account: + type: "string" + status: + type: "string" + agencies: + type: array + items: + $ref: '#/components/schemas/Organization' + contacts: + type: "array" + items: + $ref: '#/components/schemas/PublicUser' + service_url: + type: "string" + short_description: + type: "string" + long_description: + type: "string" + tags: + type: "array" + items: + type: "string" + DigitalServiceAccounts: + type: object + properties: + data: + type: array + items: + $ref: '#/components/schemas/DigitalServiceAccount' + Error: + required: + - "error" + properties: + error: + required: + - "code" + - "message" + properties: + code: + type: "string" + message: + type: "string" + type: "object" diff --git a/spec/features/admin/digital_service_accounts_spec.rb b/spec/features/admin/digital_service_accounts_spec.rb index 4a33c2746..0b7a06878 100644 --- a/spec/features/admin/digital_service_accounts_spec.rb +++ b/spec/features/admin/digital_service_accounts_spec.rb @@ -84,7 +84,7 @@ visit admin_digital_service_account_path(digital_service_account) fill_in('digital_service_account_tag_list', with: 'tag123') - page.find('#digital_service_account_tag_list').native.send_keys :tab + page.find("#tag_list_add_button").click end it 'creates a tag' do