diff --git a/.codeclimate.yml b/.codeclimate.yml index 0f3d3cfc..28ce5111 100644 --- a/.codeclimate.yml +++ b/.codeclimate.yml @@ -1,4 +1,8 @@ version: '2' +checks: + similar-code: + config: + threshold: 75 plugins: brakeman: enabled: true @@ -11,6 +15,4 @@ exclude_patterns: - db/ - vendor/ - "**/vendor/**/*" -- app/assets/images/ -- app/assets/stylesheets/uswds.css -- app/assets/stylesheets/uswds_override.css \ No newline at end of file +- app/assets/images/ \ No newline at end of file diff --git a/Gemfile b/Gemfile index e94ec66b..b0e0cc7d 100644 --- a/Gemfile +++ b/Gemfile @@ -57,6 +57,8 @@ group :development, :test do gem "rspec-rails" + gem 'pry' + # add the Ruby LSP package so it's bundled with the rest of the gems and available to VS Code gem "ruby-lsp" diff --git a/Gemfile.lock b/Gemfile.lock index 35d82216..660dce7f 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -94,6 +94,7 @@ GEM xpath (~> 3.2) codeclimate-test-reporter (1.0.7) simplecov + coderay (1.1.3) concurrent-ruby (1.3.4) connection_pool (2.4.1) crack (1.0.0) @@ -145,6 +146,7 @@ GEM net-smtp marcel (1.0.4) matrix (0.4.2) + method_source (1.1.0) mini_mime (1.1.5) minitest (5.25.1) msgpack (1.7.2) @@ -183,6 +185,9 @@ GEM activesupport (>= 7.0.0) rack railties (>= 7.0.0) + pry (0.14.2) + coderay (~> 1.1) + method_source (~> 1.0) psych (5.1.2) stringio public_suffix (6.0.1) @@ -360,6 +365,7 @@ DEPENDENCIES jwt pg propshaft (~> 0.9.0) + pry puma (>= 5.0) rails (~> 7.2.0) rails-controller-testing diff --git a/app/assets/uswds/_uswds-theme.scss b/app/assets/uswds/_uswds-theme.scss index f9bbed7f..8517c523 100644 --- a/app/assets/uswds/_uswds-theme.scss +++ b/app/assets/uswds/_uswds-theme.scss @@ -5,9 +5,12 @@ USWDS with settings overrides Add a list of changed settings in the form $setting: value. ---------------------------------------- */ - -@use "uswds-core" with ($theme-image-path: "images", - $theme-font-path: "fonts" +@use "uswds-core" with ( + $theme-image-path: "images", + $theme-font-path: "fonts", + $flex-direction-settings: ( + responsive: true + ) ); @use "uswds" as *; @@ -50,6 +53,10 @@ Add a list of changed settings in the form $setting: value. filter: invert(14%) sepia(17%) saturate(4304%) hue-rotate(190deg) brightness(94%) contrast(92%); } +.icon-white { + filter: invert(99%) sepia(2%) saturate(3661%) hue-rotate(191deg) brightness(117%) contrast(80%); +} + .usa-social-link { background-color: white; } diff --git a/app/helpers/navigation_helper.rb b/app/helpers/navigation_helper.rb new file mode 100644 index 00000000..7d0a6687 --- /dev/null +++ b/app/helpers/navigation_helper.rb @@ -0,0 +1,17 @@ +# frozen_string_literal: true + +module NavigationHelper + def utility_menu_link(image_path, href, alt, button_label) + link_to(href, + class: "display-flex flex-align-center flex-column desktop:flex-row " \ + "margin-x-1 desktop:margin-x-3 text-white text-no-wrap") do + image_tag( + "images/usa-icons/#{image_path}.svg", + class: "usa-icon--size-4 desktop:usa-icon--size-3 icon-white desktop:margin-right-1", + alt: + ) + + tag.span(button_label, class: "display-none desktop:display-block") + + tag.span(button_label, class: "desktop:display-none", style: "font-size: 0.7rem") + end + end +end diff --git a/app/views/layouts/_header.html.erb b/app/views/layouts/_header.html.erb index fdc90313..168ebd96 100644 --- a/app/views/layouts/_header.html.erb +++ b/app/views/layouts/_header.html.erb @@ -1,18 +1,198 @@ -
-
+
+
+
+
+
+ +
+ + +
+
+
+
+
+ +
+

+ Official websites use .gov
A + .gov website belongs to an official government + organization in the United States. +

+
+
+
+ +
+

+ Secure .gov websites use HTTPS
A + lock ( + + + + + ) or https:// means you’ve safely connected to + the .gov website. Share sensitive information only on official, + secure websites. +

+
+
+
+
+
+
+
+ +
\ No newline at end of file diff --git a/app/views/layouts/_utility_menu.erb b/app/views/layouts/_utility_menu.erb new file mode 100644 index 00000000..1c132557 --- /dev/null +++ b/app/views/layouts/_utility_menu.erb @@ -0,0 +1,22 @@ + +
+ <%= utility_menu_link('grid_view', 'dashboard', 'dashboard', 'Dashboard') %> + <% if current_user.role == "challenge_manager" %> + <%= utility_menu_link('emoji_events', 'http://localhost:4000/', 'challenges', 'Challenges') %> + <%= utility_menu_link('content_copy', 'evaluation_forms', 'Evaluation Forms', 'Evaluations') %> + <%= utility_menu_link('folder_open', 'manage_submissions', 'Manage Submissions', 'Submissions') %> + <% end %> + <% if current_user.role == "evaluator" %> + <%= utility_menu_link('content_copy', 'evaluations', 'Evaluate Submissions', 'Evaluations') %> + <% end %> + <% if current_user.role == "solver" %> + <%= utility_menu_link('folder_open', 'submissions', 'submissions', 'Submissions') %> + <% end %> + <%= utility_menu_link('map', 'user_guide', 'user guides', 'User Guides') %> + <%= utility_menu_link('support_agent', 'federal-agency-faqs', 'help', 'Help') %> + +
diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index 1b4aabbf..c4b7d2d9 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -25,6 +25,9 @@ <%= render "layouts/header" %> + <% if logged_in? %> + <%= render "layouts/utility_menu" %> + <% end %> <%= render "shared/flash" %> <%= yield %> diff --git a/spec/requests/dashboard_request_spec.rb b/spec/requests/dashboard_request_spec.rb index 11dce8b4..40124571 100644 --- a/spec/requests/dashboard_request_spec.rb +++ b/spec/requests/dashboard_request_spec.rb @@ -1,15 +1,79 @@ require "rails_helper" RSpec.describe "DashboardController" do + let(:user) { create_and_log_in_user } + describe "GET /" do before { get "/" } it_behaves_like "a page with footer content" + it_behaves_like "a page with header content" + + context "when logged in as public solver on the root url" do + before do + user.update(role: "solver") + get "/" + end + + it_behaves_like "a page with utility menu links for all users" + it_behaves_like "a page with utility menu links for a public solver" + end + + context "when logged in as a challenge manager on the root url" do + before do + user.update(role: "challenge_manager") + get "/" + end + + it_behaves_like "a page with utility menu links for all users" + it_behaves_like "a page with utility menu links for a challenge manager" + end + + context "when logged in as an evaluator on the root url" do + before do + user.update(role: "evaluator") + get "/" + end + + it_behaves_like "a page with utility menu links for all users" + it_behaves_like "a page with utility menu links for an evaluator" + end end describe "GET /dashboard" do before { get "/dashboard" } it_behaves_like "a page with footer content" + it_behaves_like "a page with header content" + + context "when logged in as a public solver on the dashboard" do + before do + user.update(role: "solver") + get "/dashboard" + end + + it_behaves_like "a page with utility menu links for all users" + it_behaves_like "a page with utility menu links for a public solver" + end + + context "when logged in as a challenge manager on the dashboard" do + before do + user.update(role: "challenge_manager") + get "/dashboard" + end + + it_behaves_like "a page with utility menu links for all users" + it_behaves_like "a page with utility menu links for a challenge manager" + end + + context "when logged in as an evaluator on the dashboard" do + before do + user.update(role: "evaluator") + get "/dashboard" + end + + it_behaves_like "a page with utility menu links for all users" + it_behaves_like "a page with utility menu links for an evaluator" + end end end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 9a0bfd4a..b0c677be 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -16,3 +16,22 @@ config.shared_context_metadata_behavior = :apply_to_host_groups end + +def create_and_log_in_user + user = create_user + code = "ABC123" + login_gov = instance_double(LoginGov) + allow(LoginGov).to receive(:new).and_return(login_gov) + allow(login_gov).to receive(:exchange_token_from_auth_result).with(code).and_return( + [{ email: user.email, sub: user.token }] + ) + + get "/auth/result", params: { code: } + user +end + +def create_user + email = "testsolver@example.gov" + token = SecureRandom.uuid + User.create!({ email:, token: }) +end diff --git a/spec/support/shared_examples/header.rb b/spec/support/shared_examples/header.rb new file mode 100644 index 00000000..f872e1f5 --- /dev/null +++ b/spec/support/shared_examples/header.rb @@ -0,0 +1,8 @@ +RSpec.shared_examples "a page with header content" do + it "has a header with the expected links" do + expect(response.body).to include("Find a Challenge") + expect(response.body).to include("Resources") + expect(response.body).to include("Events") + expect(response.body).to include("Contact") + end +end diff --git a/spec/support/shared_examples/utility_menu.rb b/spec/support/shared_examples/utility_menu.rb new file mode 100644 index 00000000..03c3fd70 --- /dev/null +++ b/spec/support/shared_examples/utility_menu.rb @@ -0,0 +1,27 @@ +RSpec.shared_examples "a page with utility menu links for all users" do + it "has links shared across all user roles" do + expect(response.body).to include("Dashboard") + expect(response.body).to include("User Guides") + expect(response.body).to include("Help") + end +end + +RSpec.shared_examples "a page with utility menu links for a public solver" do + it "has the right links for a public solver" do + expect(response.body).to include("Submissions") + end +end + +RSpec.shared_examples "a page with utility menu links for a challenge manager" do + it "has the right links for a challenge manager" do + expect(response.body).to include("Challenges") + expect(response.body).to include("Submissions") + expect(response.body).to include("Evaluations") + end +end + +RSpec.shared_examples "a page with utility menu links for an evaluator" do + it "has the right links for an evaluator" do + expect(response.body).to include("Evaluations") + end +end