From b9968ae3b22852ac4c5b40f0f21c3640ede00951 Mon Sep 17 00:00:00 2001 From: pvincent Date: Thu, 5 Sep 2024 13:22:20 +0400 Subject: [PATCH] hot_search --- Gemfile | 2 +- Gemfile.lock | 138 +++++++++--------- app/helpers/pagy_helper.rb | 3 +- .../controllers/hot_search_controller.js | 23 +++ app/models/application_record.rb | 3 + app/views/scores/_scores.html.erb | 19 ++- config/environments/production.rb | 4 + config/environments/test.rb | 6 +- config/initializers/backtrace_cleaning.rb | 2 +- config/initializers/hot_changes.rb | 2 +- config/initializers/rails_live_reload.rb | 25 ++-- db/schema.rb | 14 +- lib/semantic/ansi_formatter.rb | 20 +-- 13 files changed, 144 insertions(+), 117 deletions(-) create mode 100644 app/javascript/controllers/hot_search_controller.js diff --git a/Gemfile b/Gemfile index a1db836..aa724cc 100644 --- a/Gemfile +++ b/Gemfile @@ -1,6 +1,7 @@ source 'https://rubygems.org' ruby '3.1.2' +gem 'amazing_print' gem 'bootsnap', require: false gem 'dotenv-rails' gem 'importmap-rails' @@ -17,7 +18,6 @@ gem 'tailwindcss-rails' gem 'turbo-rails' group :development do - gem 'amazing_print' gem 'debug' gem 'error_highlight' gem 'htmlbeautifier' diff --git a/Gemfile.lock b/Gemfile.lock index 06ba0d4..fe9aa5e 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,29 +1,29 @@ GEM remote: https://rubygems.org/ specs: - actioncable (7.2.0) - actionpack (= 7.2.0) - activesupport (= 7.2.0) + actioncable (7.2.1) + actionpack (= 7.2.1) + activesupport (= 7.2.1) nio4r (~> 2.0) websocket-driver (>= 0.6.1) zeitwerk (~> 2.6) - actionmailbox (7.2.0) - actionpack (= 7.2.0) - activejob (= 7.2.0) - activerecord (= 7.2.0) - activestorage (= 7.2.0) - activesupport (= 7.2.0) + actionmailbox (7.2.1) + actionpack (= 7.2.1) + activejob (= 7.2.1) + activerecord (= 7.2.1) + activestorage (= 7.2.1) + activesupport (= 7.2.1) mail (>= 2.8.0) - actionmailer (7.2.0) - actionpack (= 7.2.0) - actionview (= 7.2.0) - activejob (= 7.2.0) - activesupport (= 7.2.0) + actionmailer (7.2.1) + actionpack (= 7.2.1) + actionview (= 7.2.1) + activejob (= 7.2.1) + activesupport (= 7.2.1) mail (>= 2.8.0) rails-dom-testing (~> 2.2) - actionpack (7.2.0) - actionview (= 7.2.0) - activesupport (= 7.2.0) + actionpack (7.2.1) + actionview (= 7.2.1) + activesupport (= 7.2.1) nokogiri (>= 1.8.5) racc rack (>= 2.2.4, < 3.2) @@ -32,35 +32,35 @@ GEM rails-dom-testing (~> 2.2) rails-html-sanitizer (~> 1.6) useragent (~> 0.16) - actiontext (7.2.0) - actionpack (= 7.2.0) - activerecord (= 7.2.0) - activestorage (= 7.2.0) - activesupport (= 7.2.0) + actiontext (7.2.1) + actionpack (= 7.2.1) + activerecord (= 7.2.1) + activestorage (= 7.2.1) + activesupport (= 7.2.1) globalid (>= 0.6.0) nokogiri (>= 1.8.5) - actionview (7.2.0) - activesupport (= 7.2.0) + actionview (7.2.1) + activesupport (= 7.2.1) builder (~> 3.1) erubi (~> 1.11) rails-dom-testing (~> 2.2) rails-html-sanitizer (~> 1.6) - activejob (7.2.0) - activesupport (= 7.2.0) + activejob (7.2.1) + activesupport (= 7.2.1) globalid (>= 0.3.6) - activemodel (7.2.0) - activesupport (= 7.2.0) - activerecord (7.2.0) - activemodel (= 7.2.0) - activesupport (= 7.2.0) + activemodel (7.2.1) + activesupport (= 7.2.1) + activerecord (7.2.1) + activemodel (= 7.2.1) + activesupport (= 7.2.1) timeout (>= 0.4.0) - activestorage (7.2.0) - actionpack (= 7.2.0) - activejob (= 7.2.0) - activerecord (= 7.2.0) - activesupport (= 7.2.0) + activestorage (7.2.1) + actionpack (= 7.2.1) + activejob (= 7.2.1) + activerecord (= 7.2.1) + activesupport (= 7.2.1) marcel (~> 1.0) - activesupport (7.2.0) + activesupport (7.2.1) base64 bigdecimal concurrent-ruby (~> 1.0, >= 1.3.1) @@ -111,7 +111,7 @@ GEM listen (3.9.0) rb-fsevent (~> 0.10, >= 0.10.3) rb-inotify (~> 0.9, >= 0.9.10) - logger (1.6.0) + logger (1.6.1) loofah (2.22.0) crass (~> 1.0.2) nokogiri (>= 1.12.0) @@ -124,7 +124,7 @@ GEM mini_mime (1.1.5) minitest (5.25.1) msgpack (1.7.2) - net-imap (0.4.14) + net-imap (0.4.16) date net-protocol net-pop (0.1.2) @@ -146,13 +146,13 @@ GEM racc (~> 1.4) nokogiri (1.16.7-x86_64-linux) racc (~> 1.4) - pagy (9.0.5) + pagy (9.0.8) parallel (1.26.3) - parser (3.3.4.2) + parser (3.3.5.0) ast (~> 2.4.1) racc pg (1.5.7) - prism (0.30.0) + prism (1.0.0) psych (5.1.2) stringio puma (6.4.2) @@ -166,20 +166,20 @@ GEM rackup (2.1.0) rack (>= 3) webrick (~> 1.8) - rails (7.2.0) - actioncable (= 7.2.0) - actionmailbox (= 7.2.0) - actionmailer (= 7.2.0) - actionpack (= 7.2.0) - actiontext (= 7.2.0) - actionview (= 7.2.0) - activejob (= 7.2.0) - activemodel (= 7.2.0) - activerecord (= 7.2.0) - activestorage (= 7.2.0) - activesupport (= 7.2.0) + rails (7.2.1) + actioncable (= 7.2.1) + actionmailbox (= 7.2.1) + actionmailer (= 7.2.1) + actionpack (= 7.2.1) + actiontext (= 7.2.1) + actionview (= 7.2.1) + activejob (= 7.2.1) + activemodel (= 7.2.1) + activerecord (= 7.2.1) + activestorage (= 7.2.1) + activesupport (= 7.2.1) bundler (>= 1.15.0) - railties (= 7.2.0) + railties (= 7.2.1) rails-dom-testing (2.2.0) activesupport (>= 5.0.0) minitest @@ -196,9 +196,9 @@ GEM rack railties (>= 5.1) semantic_logger (~> 4.16) - railties (7.2.0) - actionpack (= 7.2.0) - activesupport (= 7.2.0) + railties (7.2.1) + actionpack (= 7.2.1) + activesupport (= 7.2.1) irb (~> 1.13) rackup (>= 1.0.0) rake (>= 12.2) @@ -213,27 +213,24 @@ GEM rb-fsevent (0.11.2) rb-inotify (0.11.1) ffi (~> 1.0) - rbs (3.5.2) + rbs (3.5.3) logger rdoc (6.7.0) psych (>= 4.0.0) regexp_parser (2.9.2) reline (0.5.9) io-console (~> 0.5) - rexml (3.3.5) - strscan - rubocop (1.65.1) + rubocop (1.66.1) json (~> 2.3) language_server-protocol (>= 3.17.0) parallel (~> 1.10) parser (>= 3.3.0.2) rainbow (>= 2.2.2, < 4.0) regexp_parser (>= 2.4, < 3.0) - rexml (>= 3.2.5, < 4.0) - rubocop-ast (>= 1.31.1, < 2.0) + rubocop-ast (>= 1.32.2, < 2.0) ruby-progressbar (~> 1.7) unicode-display_width (>= 2.4.0, < 3.0) - rubocop-ast (1.32.1) + rubocop-ast (1.32.2) parser (>= 3.3.1.0) rubocop-packaging (0.5.2) rubocop (>= 1.33, < 2.0) @@ -246,9 +243,9 @@ GEM rubocop (~> 1.51) rubocop-thread_safety (0.5.1) rubocop (>= 0.90.0) - ruby-lsp (0.17.14) + ruby-lsp (0.17.17) language_server-protocol (~> 3.17.0) - prism (>= 0.29.0, < 0.31) + prism (~> 1.0) rbs (>= 3, < 4) sorbet-runtime (>= 0.5.10782) ruby-lsp-rails (0.3.13) @@ -257,7 +254,7 @@ GEM securerandom (0.3.1) semantic_logger (4.16.0) concurrent-ruby (~> 1.0) - sorbet-runtime (0.5.11531) + sorbet-runtime (0.5.11554) sprockets (4.2.1) concurrent-ruby (~> 1.0) rack (>= 2.2.4, < 4) @@ -268,7 +265,6 @@ GEM stimulus-rails (1.3.4) railties (>= 6.0.0) stringio (3.1.1) - strscan (3.1.0) syslog_protocol (0.9.2) tailwindcss-rails (2.7.3) railties (>= 7.0.0) @@ -282,7 +278,7 @@ GEM railties (>= 7.0.0) tailwindcss-rails (2.7.3-x86_64-linux) railties (>= 7.0.0) - thor (1.3.1) + thor (1.3.2) timeout (0.4.1) turbo-rails (2.0.6) actionpack (>= 6.0.0) @@ -296,7 +292,7 @@ GEM websocket-driver (0.7.6) websocket-extensions (>= 0.1.0) websocket-extensions (0.1.5) - zeitwerk (2.6.17) + zeitwerk (2.6.18) PLATFORMS aarch64-linux diff --git a/app/helpers/pagy_helper.rb b/app/helpers/pagy_helper.rb index d2615f7..62d3579 100644 --- a/app/helpers/pagy_helper.rb +++ b/app/helpers/pagy_helper.rb @@ -28,7 +28,8 @@ module PagyHelper url = url_for(params:) url += url.include?('?') ? '&' : '?' url += "q[#{attribute}]=" - args.last.merge!({ onkeypress: "if (event.key === \"Enter\") {Turbo.visit('#{url}'+event.target.value)}" }) + args.last.merge!({ onkeypress: "if (event.key === \"Enter\") {event.preventDefault(); Turbo.visit('#{url}'+event.target.value, { frame: 'scores', turbo: true, acceptsStreamResponse: true })}" }) + # args.last.merge!({ onkeypress: 'if (event.key === "Enter") {event.preventDefault()}' }) search_field_tag("q[#{attribute}]", value, *args) end diff --git a/app/javascript/controllers/hot_search_controller.js b/app/javascript/controllers/hot_search_controller.js new file mode 100644 index 0000000..d1434ef --- /dev/null +++ b/app/javascript/controllers/hot_search_controller.js @@ -0,0 +1,23 @@ +import { Controller } from "@hotwired/stimulus"; + +// Connects to data-controller="hot-search" +export default class extends Controller { + connect() { + this.debouncedSearch = debounce(this.debouncedSearch.bind(this), 400) + } + + debouncedSearch() { + Turbo.visit('/scores?q[name_cont]=' + this.element.value, { frame: 'scores', turbo: true, acceptsStreamResponse: true }) + } +} + +function debounce(callback, delay) { + let timeoutId; + return (...args) => { + if (timeoutId) { clearTimeout(timeoutId) } + timeoutId = setTimeout(() => { + callback(...args) + timeoutId = null + }, delay) + } +} \ No newline at end of file diff --git a/app/models/application_record.rb b/app/models/application_record.rb index e11b291..0590b32 100644 --- a/app/models/application_record.rb +++ b/app/models/application_record.rb @@ -1,4 +1,7 @@ # abstract default ActiveRecord class class ApplicationRecord < ActiveRecord::Base primary_abstract_class + + # returns a pretty name like: "MyModel#1" + def to_s = "#{self.class.name}##{id}" end diff --git a/app/views/scores/_scores.html.erb b/app/views/scores/_scores.html.erb index 7cc3b61..de2d1ae 100644 --- a/app/views/scores/_scores.html.erb +++ b/app/views/scores/_scores.html.erb @@ -1,13 +1,17 @@ -<%= turbo_frame_tag :scores do %> +INPUT: + - <%= search_form_for @q do |f| %> +
+<%= pagy_search_field(@q, :name_cont, class: "text-sm w-full h-8 text-gray-800 dark:text-gray-400 bg-gray-200 dark:bg-gray-700") %> - <%= f.label :name_cont %> - <%= f.search_field :name_cont %> +<%= search_form_for @q do |f| %> - <%= f.submit %> - <% end %> + <%= f.label :name_cont %> + <%= f.search_field :name_cont %> + <%= f.submit %> +<% end %> +<%=turbo_frame_tag :scores do %> @@ -27,6 +31,7 @@ @@ -44,4 +49,4 @@ <%== pagy_nav @pagy %> <%== pagy_info @pagy %> -<%end%> +<%end%> \ No newline at end of file diff --git a/config/environments/production.rb b/config/environments/production.rb index 0bec7aa..e056cbd 100644 --- a/config/environments/production.rb +++ b/config/environments/production.rb @@ -93,4 +93,8 @@ Rails.application.configure do # ] # Skip DNS rebinding protection for the default health check endpoint. # config.host_authorization = { exclude: ->(request) { request.path == "/up" } } + # + config.after_initialize do + config.semantic_logger.add_appender(appender: :syslog, formatter: Semantic::BasicFormatter.new) + end end diff --git a/config/environments/test.rb b/config/environments/test.rb index adbb4a6..bb76f63 100644 --- a/config/environments/test.rb +++ b/config/environments/test.rb @@ -1,4 +1,4 @@ -require "active_support/core_ext/integer/time" +require 'active_support/core_ext/integer/time' # The test environment is used exclusively to run your application's # test suite. You never need to work with it otherwise. Remember that @@ -15,12 +15,12 @@ Rails.application.configure do # this is usually not necessary, and can slow down your test suite. However, it's # recommended that you enable it in continuous integration systems to ensure eager # loading is working properly before deploying your code. - config.eager_load = ENV["CI"].present? + config.eager_load = ENV['CI'].present? # Configure public file server for tests with Cache-Control for performance. config.public_file_server.enabled = true config.public_file_server.headers = { - "Cache-Control" => "public, max-age=#{1.hour.to_i}" + 'Cache-Control' => "public, max-age=#{1.hour.to_i}" } # Show full error reports and disable caching. diff --git a/config/initializers/backtrace_cleaning.rb b/config/initializers/backtrace_cleaning.rb index f9c178d..340f9da 100644 --- a/config/initializers/backtrace_cleaning.rb +++ b/config/initializers/backtrace_cleaning.rb @@ -1,2 +1,2 @@ bc = Rails.backtrace_cleaner -bc.add_silencer { |line| %r{^lib/(monkey_patches|formatters)}.match?(line) } +bc.add_silencer { |line| %r{^lib/(monkey_patches|semantic)}.match?(line) } diff --git a/config/initializers/hot_changes.rb b/config/initializers/hot_changes.rb index e04966b..b73bff0 100644 --- a/config/initializers/hot_changes.rb +++ b/config/initializers/hot_changes.rb @@ -1,4 +1,4 @@ -return unless defined?(Rails::Server) +return unless Rails.application.server? Rails.application.config.after_initialize do Hot::Constants.on_change(:log_active_record) { |bool| ActiveRecord::Base.logger.level = bool ? :debug : :fatal } diff --git a/config/initializers/rails_live_reload.rb b/config/initializers/rails_live_reload.rb index 1fd7d08..cfbf84f 100644 --- a/config/initializers/rails_live_reload.rb +++ b/config/initializers/rails_live_reload.rb @@ -1,18 +1,17 @@ -if defined?(RailsLiveReload) && Rails.env.development? +return unless defined?(RailsLiveReload) && Rails.env.development? - RailsLiveReload.configure do |config| - # HOT Constants - config.watch(%r{/\.env$}, reload: :always) - config.watch(%r{/\.env\.sample$}) - # config.watch(%r{/config/initializers/hot_changes.rb$}) +RailsLiveReload.configure do |config| + # HOT Constants + config.watch(%r{/\.env$}, reload: :always) + config.watch(%r{/\.env\.sample$}) + # config.watch(%r{/config/initializers/hot_changes.rb$}) - # USEFUL for tailwind changes!!!! - config.watch %r{app/assets/builds/tailwind.css}, reload: :always + # USEFUL for tailwind changes!!!! + config.watch %r{app/assets/builds/tailwind.css}, reload: :always - # Rk: prevent any reload from files ending with '.tailwind.css' - config.watch %r{(app|vendor)/(assets|javascript)/.+\.(css|js|html|png|jpg)(? TOTAL_RENDERED_VIEW_DURATION ? " in #{m3}ms #{m4}" : '' log.message = "Completed #{BOLD}#{http_code}#{CLEAR} #{m2}#{duration}" if http_code / 100 == 2 - log.dimensions = AnsiDimensions.new(rails: TERMINUS_STRING, after: 1) + log.dimensions = Semantic::AnsiDimensions.new(rails: TERMINUS_STRING, after: 1) elsif http_code / 100 == 3 @memory = '║' - log.dimensions = AnsiDimensions.new(rails: "╙#{@memory}╜") + log.dimensions = Semantic::AnsiDimensions.new(rails: "╙#{@memory}╜") elsif http_code / 100 == 4 - log.dimensions = AnsiDimensions.new(rails: '╙╨╜') + log.dimensions = Semantic::AnsiDimensions.new(rails: '╙╨╜') elsif http_code / 100 == 5 - log.dimensions = AnsiDimensions.new(rails: "╙#{draw_fatal}╜") + log.dimensions = Semantic::AnsiDimensions.new(rails: "╙#{draw_fatal}╜") end elsif log.message =~ /^(Processing|Parameters)/ log.level = :debug @@ -125,7 +121,7 @@ module Semantic log.message = two_captures_last_as_bold(log.message, @regex_redirected) end elsif log.exception - log.dimensions = AnsiDimensions.new( + log.dimensions = Semantic::AnsiDimensions.new( rails: "╓#{draw_fatal(log.level.to_s.chr.upcase)}╖", after: 1, terminus: true @@ -231,11 +227,11 @@ module Semantic continuation = build_prefix('┆') result = items.map do |item| - AnsiWrapper.wrap(item, length, prefix, continuation) + Semantic::AnsiWrapper.wrap(item, length, prefix, continuation) end if log.dimensions&.terminus - terminus = AnsiWrapper.wrap(' ', length, build_terminus) + terminus = Semantic::AnsiWrapper.wrap(' ', length, build_terminus) result << terminus end
<%= pagy_search_field(@q, :name_cont, class: "text-sm w-full h-8 text-gray-800 dark:text-gray-400 bg-gray-200 dark:bg-gray-700") %> +