diff --git a/Gemfile b/Gemfile index 9a5d051..975cc50 100644 --- a/Gemfile +++ b/Gemfile @@ -8,11 +8,13 @@ gem 'pg', '>= 0.18', '< 2.0' gem 'puma', '~> 3.11' gem 'sass-rails', '~> 5.0' gem 'uglifier', '>= 1.3.0' +gem 'jquery-rails' gem 'coffee-rails', '~> 4.2' gem 'turbolinks', '~> 5' gem 'jbuilder', '~> 2.5' gem 'bootsnap', '>= 1.1.0', require: false gem 'activerecord-import' +gem 'kaminari' group :development, :test do gem 'byebug', platforms: [:mri, :mingw, :x64_mingw] diff --git a/Gemfile.lock b/Gemfile.lock index a5b5a1d..f9d5bbf 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -87,6 +87,22 @@ GEM io-like (0.3.0) jbuilder (2.9.1) activesupport (>= 4.2.0) + jquery-rails (4.3.5) + rails-dom-testing (>= 1, < 3) + railties (>= 4.2.0) + thor (>= 0.14, < 2.0) + kaminari (1.1.1) + activesupport (>= 4.1.0) + kaminari-actionview (= 1.1.1) + kaminari-activerecord (= 1.1.1) + kaminari-core (= 1.1.1) + kaminari-actionview (1.1.1) + actionview + kaminari-core (= 1.1.1) + kaminari-activerecord (1.1.1) + activerecord + kaminari-core (= 1.1.1) + kaminari-core (1.1.1) listen (3.1.5) rb-fsevent (~> 0.9, >= 0.9.4) rb-inotify (~> 0.9, >= 0.9.7) @@ -204,6 +220,8 @@ DEPENDENCIES chromedriver-helper coffee-rails (~> 4.2) jbuilder (~> 2.5) + jquery-rails + kaminari listen (>= 3.0.5, < 3.2) pg (>= 0.18, < 2.0) pry diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js index 82e6f0f..de6a7de 100644 --- a/app/assets/javascripts/application.js +++ b/app/assets/javascripts/application.js @@ -10,6 +10,7 @@ // Read Sprockets README (https://github.com/rails/sprockets#sprockets-directives) for details // about supported directives. // +//= require jquery //= require rails-ujs //= require activestorage //= require turbolinks diff --git a/app/assets/javascripts/mushrooms.coffee b/app/assets/javascripts/mushrooms.coffee new file mode 100644 index 0000000..24f83d1 --- /dev/null +++ b/app/assets/javascripts/mushrooms.coffee @@ -0,0 +1,3 @@ +# Place all the behaviors and hooks related to the matching controller here. +# All this logic will automatically be available in application.js. +# You can use CoffeeScript in this file: http://coffeescript.org/ diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.css index d05ea0f..0959a46 100644 --- a/app/assets/stylesheets/application.css +++ b/app/assets/stylesheets/application.css @@ -13,3 +13,38 @@ *= require_tree . *= require_self */ + +.body-container { + padding: 20px; + padding-right: 50px; +} + +.table-container, .filters { + height: 100vh; + overflow: scroll; +} + +thead th, .title { + position: sticky; + top: 0; +} + +th, td { + padding: 8px 16px; +} + +th, .title { + background:#eee; +} + +.title { + padding: 15px; +} + +.select-wrapper { + padding-top: 15px; +} + +label { + font-size: 1.5em !important; +} diff --git a/app/assets/stylesheets/mushrooms.scss b/app/assets/stylesheets/mushrooms.scss new file mode 100644 index 0000000..326df7f --- /dev/null +++ b/app/assets/stylesheets/mushrooms.scss @@ -0,0 +1,3 @@ +// Place all the styles related to the mushrooms controller here. +// They will automatically be included in application.css. +// You can use Sass (SCSS) here: http://sass-lang.com/ diff --git a/app/controllers/mushrooms_controller.rb b/app/controllers/mushrooms_controller.rb new file mode 100644 index 0000000..3766922 --- /dev/null +++ b/app/controllers/mushrooms_controller.rb @@ -0,0 +1,10 @@ +class MushroomsController < ApplicationController + + def index + @mushrooms = [] + + if params[:filter].present? + @mushrooms = FilterMushroom.new(params[:filter], params[:page]).run + end + end +end diff --git a/app/helpers/mushrooms_helper.rb b/app/helpers/mushrooms_helper.rb new file mode 100644 index 0000000..4b3efde --- /dev/null +++ b/app/helpers/mushrooms_helper.rb @@ -0,0 +1,16 @@ +module MushroomsHelper + include MushroomAttributesInfo + + def mushroom_attributes_values(key) + MUSHROOM_ATTRIBUTES[key].values + end + + def filter_selected?(key, value) + if params[:filter].blank? + '' + elsif params[:filter][key]&.include?(value) + 'selected' + else + end + end +end diff --git a/db/mushroom_attributes_info.rb b/app/models/concerns/mushroom_attributes_info.rb similarity index 100% rename from db/mushroom_attributes_info.rb rename to app/models/concerns/mushroom_attributes_info.rb diff --git a/app/services/filter_mushroom.rb b/app/services/filter_mushroom.rb new file mode 100644 index 0000000..8944911 --- /dev/null +++ b/app/services/filter_mushroom.rb @@ -0,0 +1,60 @@ +class FilterMushroom + attr_reader :page + + def initialize(filter_params, page) + @page = page + @mushroom_class = filter_params[:mushroom_class] + @cap_shape = filter_params[:cap_shape] + @cap_surface = filter_params[:cap_surface] + @cap_color = filter_params[:cap_color] + @bruises = filter_params[:bruises] + @odor = filter_params[:odor] + @gill_attachment = filter_params[:gill_attachment] + @gill_spacing = filter_params[:gill_spacing] + @gill_size = filter_params[:gill_size] + @gill_color = filter_params[:gill_color] + @stalk_shape = filter_params[:stalk_shape] + @stalk_root = filter_params[:stalk_root] + @stalk_surface_above_ring = filter_params[:stalk_surface_above_ring] + @stalk_surface_below_ring = filter_params[:stalk_surface_below_ring] + @stalk_color_above_ring = filter_params[:stalk_color_above_ring] + @stalk_color_below_ring = filter_params[:stalk_color_below_ring] + @veil_type = filter_params[:veil_type] + @veil_color = filter_params[:veil_color] + @ring_number = filter_params[:ring_number] + @ring_type = filter_params[:ring_type] + @spore_print_color = filter_params[:spore_print_color] + @population = filter_params[:population] + @habitat = filter_params[:habitat] + end + + def run + query = Mushroom.all + + query = query.where(mushroom_class: @mushroom_class) if @mushroom_class.present? + query = query.where(cap_shape: @cap_shape) if @cap_shape.present? + query = query.where(cap_surface: @cap_surface) if @cap_surface.present? + query = query.where(cap_color: @cap_color) if @cap_color.present? + query = query.where(bruises: @bruises) if @bruises.present? + query = query.where(odor: @odor) if @odor.present? + query = query.where(gill_attachment: @gill_attachment) if @gill_attachment.present? + query = query.where(gill_spacing: @gill_spacing) if @gill_spacing.present? + query = query.where(gill_size: @gill_size) if @gill_size.present? + query = query.where(gill_color: @gill_color) if @gill_color.present? + query = query.where(stalk_shape: @stalk_shape) if @stalk_shape.present? + query = query.where(stalk_root: @stalk_root) if @stalk_root.present? + query = query.where(stalk_surface_above_ring: @stalk_surface_above_ring) if @stalk_surface_above_ring.present? + query = query.where(stalk_surface_below_ring: @stalk_surface_below_ring) if @stalk_surface_below_ring.present? + query = query.where(stalk_color_above_ring: @stalk_color_above_ring) if @stalk_color_above_ring.present? + query = query.where(stalk_color_below_ring: @stalk_color_below_ring) if @stalk_color_below_ring.present? + query = query.where(veil_type: @veil_type) if @veil_type.present? + query = query.where(veil_color: @veil_color) if @veil_color.present? + query = query.where(ring_number: @ring_number) if @ring_number.present? + query = query.where(ring_type: @ring_type) if @ring_type.present? + query = query.where(spore_print_color: @spore_print_color) if @spore_print_color.present? + query = query.where(population: @population) if @population.present? + query = query.where(habitat: @habitat) if @habitat.present? + + query.page(page) + end +end diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index ffeef56..d104f74 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -1,15 +1,22 @@ + Mushrooms <%= csrf_meta_tags %> <%= csp_meta_tag %> - <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %> + <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %> <%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %> + + <%# Materialize CDN %> + + - <%= yield %> +
+ <%= yield %> +
diff --git a/app/views/mushrooms/_filter_form.html.erb b/app/views/mushrooms/_filter_form.html.erb new file mode 100644 index 0000000..0f6bc6a --- /dev/null +++ b/app/views/mushrooms/_filter_form.html.erb @@ -0,0 +1,79 @@ +<%= form_for :filter, url: root_path, method: 'GET', id: 'my-form' do |f| %> + <%# mushroom class %> + <%= render 'filter_option', field: :mushroom_class, placeholder: 'Select class' %> + + <%# cap-shape %> + <%= render 'filter_option', field: :cap_shape, placeholder: 'Select cap shape' %> + + <%# cap-surface %> + <%= render 'filter_option', field: :cap_surface, placeholder: 'Select cap surface' %> + + <%# cap-color %> + <%= render 'filter_option', field: :cap_color, placeholder: 'Select cap color' %> + + <%# bruises %> + <%= render 'filter_option', field: :bruises, placeholder: 'Select bruises' %> + + <%# odor %> + <%= render 'filter_option', field: :odor, placeholder: 'Select odor' %> + + <%# gill-attachment %> + <%= render 'filter_option', field: :gill_attachment, placeholder: 'Select gill attachment' %> + + <%# gill-spacing %> + <%= render 'filter_option', field: :gill_spacing, placeholder: 'Select gill spacing' %> + + <%# gill-size %> + <%= render 'filter_option', field: :gill_size, placeholder: 'Select gill size' %> + + <%# gill-color %> + <%= render 'filter_option', field: :gill_color, placeholder: 'Select gill color' %> + + <%# stalk-shape %> + <%= render 'filter_option', field: :stalk_shape, placeholder: 'Select stalk shape' %> + + <%# stalk-root %> + <%= render 'filter_option', field: :stalk_root, placeholder: 'Select stalk root' %> + + <%# stalk-surface-above-ring %> + <%= render 'filter_option', field: :stalk_surface_above_ring, placeholder: 'Select stalk surface above ring' %> + + <%# stalk-surface-below-ring %> + <%= render 'filter_option', field: :stalk_surface_below_ring, placeholder: 'Select stalk surface below ring' %> + + <%# stalk-color-above-ring %> + <%= render 'filter_option', field: :stalk_color_above_ring, placeholder: 'Select stalk color above ring' %> + + <%# stalk-color-below-ring %> + <%= render 'filter_option', field: :stalk_color_below_ring, placeholder: 'Select stalk color below ring' %> + + <%# veil-type %> + <%= render 'filter_option', field: :veil_type, placeholder: 'Select veil type' %> + + <%# veil-color %> + <%= render 'filter_option', field: :veil_color, placeholder: 'Select veil color' %> + + <%# ring-number %> + <%= render 'filter_option', field: :ring_number, placeholder: 'Select ring number' %> + + <%# ring-type %> + <%= render 'filter_option', field: :ring_type, placeholder: 'Select ring type' %> + + <%# spore-print-color %> + <%= render 'filter_option', field: :spore_print_color, placeholder: 'Select spore print color' %> + + <%# population %> + <%= render 'filter_option', field: :population, placeholder: 'Select population' %> + + <%# habitat %> + <%= render 'filter_option', field: :habitat, placeholder: 'Select habitat' %> + + <%= f.submit 'Apply Filter', class: 'btn btn-large right' %> + <%= link_to 'Reset', root_path, class: 'btn btn-large red reset' %> +<% end %> + + diff --git a/app/views/mushrooms/_filter_option.html.erb b/app/views/mushrooms/_filter_option.html.erb new file mode 100644 index 0000000..4a5dc80 --- /dev/null +++ b/app/views/mushrooms/_filter_option.html.erb @@ -0,0 +1,12 @@ +
+ + + +
diff --git a/app/views/mushrooms/_table.html.erb b/app/views/mushrooms/_table.html.erb new file mode 100644 index 0000000..4413f73 --- /dev/null +++ b/app/views/mushrooms/_table.html.erb @@ -0,0 +1,65 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + <% row_count = @mushrooms.limit_value * (@mushrooms.current_page - 1)%> + + <% @mushrooms.each do |mushroom| %> + <% row_count += 1 %> + + + + + + + + + + + + + + + + + + + + + + + + + + + + <% end %> + +
#ClassCap ShapeCap SurfaceCap ColorBruisesOdorGill AttachmentGill SpacingGill SizeGill ColorStalk ShapeStalk RootStalk Surface Above RingStalk Surface Below RingStalk Color Above RingStalk Color Below RingVeil TypeVeil ColorRing NumberRing TypeSpore Print ColorPopulationHabitat
<%= row_count %><%= mushroom.mushroom_class %><%= mushroom.cap_shape %><%= mushroom.cap_surface %><%= mushroom.cap_color %><%= mushroom.bruises %><%= mushroom.odor %><%= mushroom.gill_attachment %><%= mushroom.gill_spacing %><%= mushroom.gill_size %><%= mushroom.gill_color %><%= mushroom.stalk_shape %><%= mushroom.stalk_root %><%= mushroom.stalk_surface_above_ring %><%= mushroom.stalk_surface_below_ring %><%= mushroom.stalk_color_above_ring %><%= mushroom.stalk_color_below_ring %><%= mushroom.veil_type %><%= mushroom.veil_color %><%= mushroom.ring_number %><%= mushroom.ring_type %><%= mushroom.spore_print_color %><%= mushroom.population %><%= mushroom.habitat %>
diff --git a/app/views/mushrooms/index.html.erb b/app/views/mushrooms/index.html.erb new file mode 100644 index 0000000..67a9426 --- /dev/null +++ b/app/views/mushrooms/index.html.erb @@ -0,0 +1,15 @@ +

Mushrooms

+ +
+
+

Filters


+ <%= render 'filter_form' %> +
+ + <% if @mushrooms.present? %> +
+ <%= render 'table' %> + <%= paginate @mushrooms %> +
+ <% end %> +
diff --git a/config/routes.rb b/config/routes.rb index 787824f..268d4a9 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,3 +1,3 @@ Rails.application.routes.draw do - # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html + root 'mushrooms#index' end diff --git a/db/seeds.rb b/db/seeds.rb index a817ba4..f29ea4a 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -1,5 +1,4 @@ require 'csv' -require_relative 'mushroom_attributes_info' include MushroomAttributesInfo @@ -44,7 +43,7 @@ } ] - imported_mushrooms = Mushroom.import mushrooms, batch_size: 100 + imported_mushrooms = Mushroom.import mushrooms, batch_size: 1000 imported_mushrooms.failed_instances.each do |failure| failed_row_count += 1 diff --git a/test/controllers/mushrooms_controller_test.rb b/test/controllers/mushrooms_controller_test.rb new file mode 100644 index 0000000..7afdc3a --- /dev/null +++ b/test/controllers/mushrooms_controller_test.rb @@ -0,0 +1,7 @@ +require 'test_helper' + +class MushroomsControllerTest < ActionDispatch::IntegrationTest + # test "the truth" do + # assert true + # end +end