Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Make problem severity configurable #1562

Merged
merged 17 commits into from
Jan 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -97,3 +97,5 @@ gem "sqlite3_ar_regexp", "~> 2.2"
gem "mittsu", github: "danini-the-panini/mittsu", ref: "7f44c46"

gem "view_component", "~> 3.10"

gem "rails-controller-testing", "~> 1.0", group: :test
5 changes: 5 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -300,6 +300,10 @@ GEM
activesupport (= 7.0.8)
bundler (>= 1.15.0)
railties (= 7.0.8)
rails-controller-testing (1.0.5)
actionpack (>= 5.0.1.rc1)
actionview (>= 5.0.1.rc1)
activesupport (>= 5.0.1.rc1)
rails-dom-testing (2.2.0)
activesupport (>= 5.0.0)
minitest
Expand Down Expand Up @@ -506,6 +510,7 @@ DEPENDENCIES
public_suffix (~> 5.0)
puma (~> 6.4)
rails (~> 7.0.8)
rails-controller-testing (~> 1.0)
rails-settings-cached (~> 2.9)
redis (~> 5.0)
rspec-rails
Expand Down
2 changes: 1 addition & 1 deletion app/controllers/problems_controller.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
class ProblemsController < ApplicationController
def index
page = params[:page] || 1
@problems = Problem.all.page(page).per(50).order([:category, :problematic_type])
@problems = Problem.visible(current_user.problem_settings).page(page).per(50).order([:category, :problematic_type])
end
end
6 changes: 6 additions & 0 deletions app/controllers/settings_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ def update
update_pagination_settings(params[:pagination])
update_renderer_settings(params[:renderer])
update_tag_cloud_settings(params[:tag_cloud])
update_problem_settings(params[:problems])
@user.save!
# Save site-wide settings if user is an admin
if current_user.admin?
Expand Down Expand Up @@ -56,6 +57,11 @@ def update_renderer_settings(settings)
}
end

def update_problem_settings(settings)
return unless settings
@user.problem_settings = settings
end

def update_folder_settings(settings)
return unless settings
SiteSettings.model_path_template = settings[:model_path_template].gsub(/^\//, "") # Remove leading slashes
Expand Down
14 changes: 3 additions & 11 deletions app/helpers/problems_helper.rb
Original file line number Diff line number Diff line change
@@ -1,18 +1,10 @@
module ProblemsHelper
def problem_severity(problem)
case problem.category.to_sym
when :missing
"danger"
when :nesting, :duplicate
"warning"
else
"info"
end
current_user.problem_settings[problem.category]&.to_sym || :silent
end

def max_problem_severity
return "danger" if Problem.where(category: :missing).count > 0
return "warning" if Problem.where(category: [:nesting, :duplicate]).count > 0
"info"
severities = Problem.select(:category).distinct.map { |p| problem_severity(p) }
severities.max_by { |p| Problem::SEVERITIES.find_index(p) }
end
end
23 changes: 22 additions & 1 deletion app/models/problem.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,35 @@ class Problem < ApplicationRecord

validates :category, uniqueness: {scope: :problematic}, presence: true

enum :category, [
scope :visible, ->(settings) {
enabled = settings.select { |cat, sev| sev.to_sym != :silent }
where(category: enabled.keys)
}

CATEGORIES = [
:missing,
:empty,
:destination_exists, # No longer used, but kept for compatibility
:nesting,
:inefficient,
:duplicate
]
enum :category, CATEGORIES

SEVERITIES = [
:silent,
:info,
:warning,
:danger
]

DEFAULT_SEVERITIES = {
missing: :danger,
empty: :info,
nesting: :warning,
inefficient: :info,
duplicate: :warning
}

def self.create_or_clear(problematic, cat, present, options = {})
if present
Expand Down
2 changes: 1 addition & 1 deletion app/views/application/_navbar.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@
</div>
<% end %>
</li>
<% if Problem.count > 0 %>
<% if Problem.visible(current_user.problem_settings).count > 0 %>
<li class="nav-item">
<%= nav_link 'exclamation-triangle-fill',
Problem.model_name.human.pluralize,
Expand Down
24 changes: 24 additions & 0 deletions app/views/settings/_problem_settings.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<div class="card mb-2">
<h3 class="card-header"><%= t(".title") %></h3>
<div class="card-body">
<p class='lead'>
<%= t(".description") %>
</p>
<% Problem::CATEGORIES.each do |category| %>
<% next if Problem::DEFAULT_SEVERITIES[category].nil? # Skip deprecated categories; they don't appear in the defaults list %>
<div class="row">
<%= form.label t("problems.categories.#{category}"),
for: "problems[#{category}]",
class: "col col-form-label"
%>
<div class="col">
<%= form.select "problems[#{category}]",
Problem::SEVERITIES.map { |s| [t("problems.severities.#{s}"), s] },
{selected: @user.problem_settings[category.to_s]},
class: "form-select"
%>
</div>
</div>
<% end %>
</div>
</div>
2 changes: 1 addition & 1 deletion app/views/settings/_renderer_settings.html.erb
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<div class="card">
<div class="card mb-2">
<h3 class="card-header">Renderer</h3>
<div class="card-body">
<p class='lead'>
Expand Down
35 changes: 19 additions & 16 deletions app/views/settings/_tag_cloud_settings.html.erb
Original file line number Diff line number Diff line change
@@ -1,33 +1,36 @@
<div class="card">
<div class="card mb-2">
<h3 class="card-header">Tag Cloud</h3>
<div class="card-body">
<div class="row mb-2">
<%= form.label "Minimum count of tag for display", for: "tag_cloud[threshold]", class: "col-sm-8 col-form-label"%>
<div class="col-sm-4">
<div class="row">
<%= form.label "Minimum count of tag for display", for: "tag_cloud[threshold]", class: "col col-form-label"%>
<div class="col">
<%= form.text_field "tag_cloud[threshold]", value: @user.tag_cloud_settings["threshold"], class: "form-control" %>
</div>
</div>
<div class="row mb-2">
<%= form.label "Display tag count for individual tags", for: "tag_cloud[heatmap]", class: "col-sm-8 col-form-label"%>
<div class="col-sm-4 form-check form-switch">
<div class="row">
<%= form.label "Display tag count for individual tags", for: "tag_cloud[heatmap]", class: "col col-form-label"%>
<div class="col form-check form-switch">
<%= form.check_box "tag_cloud[heatmap]", checked: @user.tag_cloud_settings["heatmap"], class: "form-check-input" %>
</div>
</div>
<div class="row mb-2">
<%= form.label "Hide unrelated tags in filtered lists", for: "tag_cloud[hide_unrelated]", class: "col-sm-8 col-form-label"%>
<div class="col-sm-4 form-check form-switch">
<div class="row">
<%= form.label "Hide unrelated tags in filtered lists", for: "tag_cloud[hide_unrelated]", class: "col col-form-label"%>
<div class="col form-check form-switch">
<%= form.check_box "tag_cloud[hide_unrelated]", checked: @user.tag_cloud_settings["hide_unrelated"], class: "form-check-input" %>
</div>
</div>
<div class="row mb-2">
<%= form.label "Sorting", for: "tag_cloud[sorting]", class: "col-sm-8 col-form-label"%>
<div class="col-sm-4">
<%= form.select "tag_cloud[sorting]", ["frequency","alphabetical"], selected: @user.tag_cloud_settings["sorting"], class: "form-select" %>
<div class="row">
<%= form.label "Sorting", for: "tag_cloud[sorting]", class: "col col-form-label"%>
<div class="col">
<%= form.select "tag_cloud[sorting]", ["frequency","alphabetical"],
{selected: @user.tag_cloud_settings["sorting"]},
class: "form-select"
%>
</div>
</div>
<div class="row mb-2">
<%= form.label "Use delimiter to represent keypairs", for: "tag_cloud[keypair]", class: "col-sm-8 col-form-label"%>
<div class="col-sm-4 form-check form-switch">
<%= form.label "Use delimiter to represent keypairs", for: "tag_cloud[keypair]", class: "col col-form-label"%>
<div class="col form-check form-switch">
<%= form.check_box "tag_cloud[keypair]", checked: @user.tag_cloud_settings["keypair"], class: "form-check-input" %>
</div>
</div>
Expand Down
1 change: 1 addition & 0 deletions app/views/settings/show.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
</div>
<div class="col">
<%= render "renderer_settings", form: form %>
<%= render "problem_settings", form: form %>
</div>
</div>

Expand Down
1 change: 1 addition & 0 deletions config/i18n-tasks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ search:
ignore_unused:
- 'activerecord.attributes.*'
- 'activerecord.models.*'
- 'problems.categories.*'
# - '{devise,kaminari,will_paginate}.*'
# - 'simple_form.{yes,no}'
# - 'simple_form.{placeholders,hints,labels}.*'
Expand Down
14 changes: 14 additions & 0 deletions config/locales/en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,12 @@ en:
message: This file is duplicated in other models. You may wish to remove some.
title: Duplicated files
problems:
categories:
duplicate: Duplicate files
empty: Model has no files
inefficient: Inefficient formats
missing: Missing files or folders
nesting: Model contains other models
library:
missing: Library folder not found
model:
Expand All @@ -60,11 +66,19 @@ en:
description: Duplicated file
model_file_inefficient:
description: Inefficient file format
severities:
danger: Danger
info: Info
silent: Ignored
warning: Warning
renderer:
style:
lambert: Realistically shaded
normals: Surface direction
settings:
problem_settings:
description: Change the severity of detected problems, or ignore them completely.
title: Problem Detection
renderer_settings:
auto_load_max_size:
always: Always
Expand Down
5 changes: 5 additions & 0 deletions db/migrate/20240122114207_add_problem_settings_to_user.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
class AddProblemSettingsToUser < ActiveRecord::Migration[7.0]
def change
add_column :users, :problem_settings, :json, default: Problem::DEFAULT_SEVERITIES
end
end
3 changes: 2 additions & 1 deletion db/schema.rb

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions spec/factories/problem.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
FactoryBot.define do
factory :problem do
category { :missing }
problematic { association :model_file }
end
end
36 changes: 25 additions & 11 deletions spec/helpers/problems_helper_spec.rb
Original file line number Diff line number Diff line change
@@ -1,15 +1,29 @@
require "rails_helper"

# Specs in this file have access to a helper object that includes
# the ProblemsHelper. For example:
#
# describe ProblemsHelper do
# describe "string concat" do
# it "concats two strings with spaces" do
# expect(helper.concat_strings("this","that")).to eq("this that")
# end
# end
# end
RSpec.describe ProblemsHelper do
pending "add some examples to (or delete) #{__FILE__}"
include Devise::Test::ControllerHelpers
let(:model) { create(:model) }

before do
sign_in User.first
end

it "converts a problem to a severity level" do
expect(helper.problem_severity(
Problem.new(category: :duplicate, problematic: model)
)).to eq :warning
end

it "works out the maximum severity from a set of problems (warning)" do
Problem.create(category: :duplicate, problematic: model)
Problem.create(category: :inefficient, problematic: model)
expect(helper.max_problem_severity).to eq :warning
end

it "works out the maximum severity from a set of problems (danger)" do
Problem.create(category: :missing, problematic: model)
Problem.create(category: :duplicate, problematic: model)
Problem.create(category: :inefficient, problematic: model)
expect(helper.max_problem_severity).to eq :danger
end
end
26 changes: 25 additions & 1 deletion spec/models/problem_spec.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,29 @@
require "rails_helper"

RSpec.describe Problem do
pending "add some examples to (or delete) #{__FILE__}"
describe "querying visible scope" do
let(:settings) do
{
missing: :silent,
empty: :info,
nesting: :warning,
inefficient: :info,
duplicate: :warning
}
end

before do
create_list(:problem, 3, :missing)
create_list(:problem, 3, :inefficient)
end

it "lists visible problems" do
expect(described_class.visible(settings).length).to eq 3
expect(described_class.visible(settings).map { |x| x.category.to_sym }).to include :inefficient
end

it "does not include silenced problems" do
expect(described_class.visible(settings).map { |x| x.category.to_sym }).not_to include :missing
end
end
end
27 changes: 26 additions & 1 deletion spec/requests/problems_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,34 @@

RSpec.describe "Problems" do
describe "GET /index" do
it "returns http success" do
before do
create_list(:problem, 2, category: :inefficient)
create_list(:problem, 3, category: :missing)
sign_in User.first
end

it "returns success" do
get "/problems/index"
expect(response).to have_http_status(:success)
end

it "lists problems" do
get "/problems/index"
expect(assigns(:problems).length).to eq 5
end

context "with silenced problems" do
before do
u = User.first
u.problem_settings["missing"] = "silent"
u.save!
sign_in u
end

it "doesn't show problems with silent severity" do
get "/problems/index"
expect(assigns(:problems).length).to eq 2
end
end
end
end
Loading