diff --git a/app/jobs/scan/check_model_integrity_job.rb b/app/jobs/scan/check_model_integrity_job.rb index d2b97be9a..44067f736 100644 --- a/app/jobs/scan/check_model_integrity_job.rb +++ b/app/jobs/scan/check_model_integrity_job.rb @@ -7,6 +7,8 @@ def perform(model_id) Problem.create_or_clear(model, :missing, !File.exist?(File.join(model.library.path, model.path))) Problem.create_or_clear model, :empty, (model.model_files.count == 0) Problem.create_or_clear model, :nesting, model.contains_other_models? + Problem.create_or_clear model, :no_image, model.image_files.empty? + Problem.create_or_clear model, :no_3d_model, model.three_d_files.empty? model.model_files.each do |f| Problem.create_or_clear(f, :missing, !File.exist?(File.join(model.library.path, model.path, f.filename))) end diff --git a/app/models/model.rb b/app/models/model.rb index e6e51bb75..d3c0c01e8 100644 --- a/app/models/model.rb +++ b/app/models/model.rb @@ -107,6 +107,14 @@ def new? tags.where(name: SiteSettings.model_tags_auto_tag_new).any? end + def image_files + model_files.select(&:is_image?) + end + + def three_d_files + model_files.select(&:is_3d_model?) + end + private def normalize_license diff --git a/app/models/model_file.rb b/app/models/model_file.rb index f7eb84bcc..0899a9a93 100644 --- a/app/models/model_file.rb +++ b/app/models/model_file.rb @@ -18,6 +18,10 @@ def is_image? SupportedMimeTypes.image_extensions.include? extension end + def is_3d_model? + SupportedMimeTypes.model_extensions.include? extension + end + def mime_type Mime::Type.lookup_by_extension(extension) end diff --git a/app/models/problem.rb b/app/models/problem.rb index 18f05aa10..2033046f5 100644 --- a/app/models/problem.rb +++ b/app/models/problem.rb @@ -16,7 +16,9 @@ class Problem < ApplicationRecord :destination_exists, # No longer used, but kept for compatibility :nesting, :inefficient, - :duplicate + :duplicate, + :no_image, + :no_3d_model ] enum :category, CATEGORIES @@ -32,7 +34,9 @@ class Problem < ApplicationRecord empty: :info, nesting: :warning, inefficient: :info, - duplicate: :warning + duplicate: :warning, + no_image: :silent, + no_3d_model: :silent } def self.create_or_clear(problematic, cat, present, options = {}) diff --git a/app/views/problems/_model_no_3d_model.html.erb b/app/views/problems/_model_no_3d_model.html.erb new file mode 100644 index 000000000..e75c8c368 --- /dev/null +++ b/app/views/problems/_model_no_3d_model.html.erb @@ -0,0 +1,4 @@ +<%= icon("question-square", t(".title")) %> +<%= link_to problem.problematic.name, [problem.problematic.library, problem.problematic] %> +<%= t ".title" %> +<%= link_to "Open", [problem.problematic.library, problem.problematic], class: "btn btn-primary" %> diff --git a/app/views/problems/_model_no_image.html.erb b/app/views/problems/_model_no_image.html.erb new file mode 100644 index 000000000..e75c8c368 --- /dev/null +++ b/app/views/problems/_model_no_image.html.erb @@ -0,0 +1,4 @@ +<%= icon("question-square", t(".title")) %> +<%= link_to problem.problematic.name, [problem.problematic.library, problem.problematic] %> +<%= t ".title" %> +<%= link_to "Open", [problem.problematic.library, problem.problematic], class: "btn btn-primary" %> diff --git a/config/locales/en.yml b/config/locales/en.yml index 5a7c78aca..f5f6c18fd 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -110,6 +110,8 @@ en: inefficient: Inefficient formats missing: Missing files or folders nesting: Model contains other models + no_3d_model: Model has no 3D files + no_image: Model has no image files filters: apply_filters: Apply category: Category @@ -143,6 +145,12 @@ en: description: The model folder on disk contains other models. You may wish to merge them into this one, or move them out. title: Contains other models warning: Bulk merging moves all files from the models above into this one, and removes them. File metadata is preserved, but any model metadata will be lost! + model_no_3d_model: + description: This model contains no 3D files. That is unlikely to be correct. + title: No 3D files in model + model_no_image: + description: This model contains no image files. Adding one might make it easier to browse. + title: No image files in model severities: danger: Danger info: Info diff --git a/spec/jobs/scan/check_model_integrity_job_spec.rb b/spec/jobs/scan/check_model_integrity_job_spec.rb index 20cf28330..3100153df 100644 --- a/spec/jobs/scan/check_model_integrity_job_spec.rb +++ b/spec/jobs/scan/check_model_integrity_job_spec.rb @@ -2,29 +2,49 @@ require "support/mock_directory" RSpec.describe Scan::CheckModelIntegrityJob do - around do |ex| - MockDirectory.create([ - "model_one/test.stl" - ]) do |path| - @library_path = path - ex.run + context "when checking for missing files" do + around do |ex| + MockDirectory.create([ + "model_one/test.stl" + ]) do |path| + @library_path = path + ex.run + end + end + + # rubocop:disable RSpec/InstanceVariable + let(:library) { create(:library, path: @library_path) } + # rubocop:enable RSpec/InstanceVariable + + it "flags models with no folder as a problem" do + model = create(:model, library: library, path: "missing") + described_class.perform_now(model.id) + expect(model.problems.map(&:category)).to include("missing") end - end - # rubocop:disable RSpec/InstanceVariable - let(:library) { create(:library, path: @library_path) } - # rubocop:enable RSpec/InstanceVariable + it "flags up problems for files that don't exist on disk" do + thing = create(:model, path: "model_one", library: library) + create(:model_file, filename: "missing.stl", model: thing) + described_class.perform_now(thing.id) + expect(thing.model_files.first.problems.map(&:category)).to include("missing") + end + end - it "flags models with no folder as a problem" do - model = create(:model, library: library, path: "missing") - expect { described_class.perform_now(model.id) }.to change(Problem, :count).from(0).to(2) - expect(model.problems.map(&:category)).to eq ["missing", "empty"] + context "when checking for missing image files" do + it "flags models without images as a problem" do + model = create(:model) + create(:model_file, filename: "3d.stl", model: model) + described_class.perform_now(model.id) + expect(model.problems.map(&:category)).to include("no_image") + end end - it "flags up problems for files that don't exist on disk" do - thing = create(:model, path: "model_one", library: library) - create(:model_file, filename: "missing.stl", model: thing) - expect { described_class.perform_now(thing.id) }.to change(Problem, :count).from(0).to(1) - expect(thing.model_files.first.problems.first.category).to eq "missing" + context "when checking for missing 3d files" do + it "flags models without 3d files as a problem" do + model = create(:model) + create(:model_file, filename: "image.jpg", model: model) + described_class.perform_now(model.id) + expect(model.problems.map(&:category)).to include("no_3d_model") + end end end