mysql_genius 0.1.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. data/.github/FUNDING.yml +5 -0
  3. data/.github/workflows/ci.yml +30 -7
  4. data/.gitignore +3 -0
  5. data/.rubocop.yml +24 -0
  6. data/CHANGELOG.md +32 -0
  7. data/Gemfile +7 -2
  8. data/README.md +50 -38
  9. data/Rakefile +3 -1
  10. data/app/controllers/concerns/mysql_genius/ai_features.rb +90 -52
  11. data/app/controllers/concerns/mysql_genius/database_analysis.rb +73 -45
  12. data/app/controllers/concerns/mysql_genius/query_execution.rb +18 -16
  13. data/app/controllers/mysql_genius/base_controller.rb +3 -1
  14. data/app/controllers/mysql_genius/queries_controller.rb +19 -12
  15. data/app/services/mysql_genius/ai_client.rb +10 -3
  16. data/app/services/mysql_genius/ai_optimization_service.rb +8 -4
  17. data/app/services/mysql_genius/ai_suggestion_service.rb +6 -3
  18. data/app/views/layouts/mysql_genius/application.html.erb +141 -5
  19. data/app/views/mysql_genius/queries/_tab_dashboard.html.erb +95 -0
  20. data/app/views/mysql_genius/queries/_tab_duplicate_indexes.html.erb +11 -0
  21. data/app/views/mysql_genius/queries/_tab_query_explorer.html.erb +110 -0
  22. data/app/views/mysql_genius/queries/_tab_table_sizes.html.erb +6 -4
  23. data/app/views/mysql_genius/queries/_tab_unused_indexes.html.erb +11 -0
  24. data/app/views/mysql_genius/queries/index.html.erb +377 -52
  25. data/bin/console +1 -0
  26. data/config/routes.rb +2 -0
  27. data/docs/screenshots/dashboard.png +0 -0
  28. data/docs/screenshots/query_explore.png +0 -0
  29. data/docs/superpowers/plans/2026-04-08-dashboard-first-redesign.md +741 -0
  30. data/docs/superpowers/specs/2026-04-08-dashboard-first-redesign.md +87 -0
  31. data/lib/generators/mysql_genius/install/install_generator.rb +19 -0
  32. data/lib/generators/mysql_genius/install/templates/initializer.rb +56 -0
  33. data/lib/mysql_genius/configuration.rb +8 -6
  34. data/lib/mysql_genius/engine.rb +2 -0
  35. data/lib/mysql_genius/slow_query_monitor.rb +30 -25
  36. data/lib/mysql_genius/sql_validator.rb +6 -4
  37. data/lib/mysql_genius/version.rb +3 -1
  38. data/lib/mysql_genius.rb +2 -0
  39. data/mysql_genius.gemspec +9 -8
  40. metadata +31 -15
  41. data/app/views/mysql_genius/queries/_tab_sql_query.html.erb +0 -40
  42. data/app/views/mysql_genius/queries/_tab_visual_builder.html.erb +0 -61
  43. data/docs/screenshots/sql_query.png +0 -0
  44. data/docs/screenshots/visual_builder.png +0 -0
@@ -0,0 +1,87 @@
1
+ # Dashboard-First Redesign
2
+
3
+ Redesign the default landing experience to lead with PgHero-style monitoring instead of the SQL query builder. Based on Reddit feedback that the current Visual Builder default makes the engine look like "another DB GUI" rather than a MySQL performance dashboard.
4
+
5
+ ## Changes
6
+
7
+ ### 1. New Dashboard Tab (default)
8
+
9
+ A new tab that becomes the active tab on page load. Loads all data immediately via parallel AJAX calls to existing endpoints. Four stacked sections:
10
+
11
+ **Server Summary** (reuses `server_overview` endpoint)
12
+ - Four cards in a responsive grid: Server (version, uptime), Connections (used/max progress bar), InnoDB Buffer Pool (hit rate progress bar), Query Activity (questions/sec, slow queries count)
13
+
14
+ **Top 5 Slow Queries** (reuses `slow_queries` endpoint)
15
+ - Compact table: duration, timestamp, truncated SQL
16
+ - "View all" link switches to Slow Queries tab
17
+ - If Redis not configured: muted placeholder "Configure `redis_url` to monitor slow queries."
18
+
19
+ **Top 5 Expensive Queries** (reuses `query_stats` endpoint with new `limit` param)
20
+ - Compact table: query digest, calls, total time, avg time
21
+ - Sorted by total time descending
22
+ - "View all" link switches to Query Stats tab
23
+ - If `performance_schema` unavailable: muted placeholder
24
+
25
+ **Index Alerts** (reuses `duplicate_indexes` and `unused_indexes` endpoints)
26
+ - Two badge cards showing counts: "X duplicate indexes", "X unused indexes"
27
+ - Green checkmark if count is zero
28
+ - Each badge is clickable, switches to the corresponding tab
29
+
30
+ ### 2. Query Explorer Tab (merged Visual Builder + SQL Query)
31
+
32
+ The two existing query tabs merge into one "Query Explorer" tab with a mode toggle:
33
+
34
+ - **Visual mode** -- existing visual builder UI (table selector, columns, filters, ordering)
35
+ - **SQL mode** -- existing raw SQL textarea with AI suggestion panel
36
+ - Small toggle buttons at top of tab to switch modes
37
+ - Default mode: Visual
38
+ - SQL generated by visual builder carries over when switching to SQL mode (existing behavior preserved)
39
+ - Shared results area unchanged
40
+
41
+ ### 3. Tab Reorder
42
+
43
+ New order:
44
+ 1. Dashboard (new, default active)
45
+ 2. Slow Queries
46
+ 3. Query Stats
47
+ 4. Server
48
+ 5. Table Sizes
49
+ 6. Unused Indexes
50
+ 7. Duplicate Indexes
51
+ 8. Query Explorer (merged)
52
+ 9. AI Tools (conditional on `@ai_enabled`)
53
+
54
+ ### 4. Backend Change
55
+
56
+ Add `limit` parameter support to the `query_stats` action. When present, cap the result set to the given limit. The dashboard passes `limit=5`; the Query Stats tab continues to omit it for the full list.
57
+
58
+ ### 5. Gemspec Description Update
59
+
60
+ Change description to lead with monitoring:
61
+ > "MysqlGenius gives Rails apps a mountable performance dashboard for MySQL databases. Monitor slow queries, analyze query statistics from performance_schema, detect unused and duplicate indexes, and explore your database with optional AI-powered optimization."
62
+
63
+ ### 6. README Updates
64
+
65
+ - Reorder screenshots section to lead with Dashboard
66
+ - Update "Usage" section to reflect new tab order and dashboard-first experience
67
+ - Add Dashboard screenshot placeholder
68
+
69
+ ## Not Changing
70
+
71
+ - No new routes -- dashboard reuses existing endpoints
72
+ - No new controller actions -- only a `limit` param added to `query_stats`
73
+ - All existing tab partials remain intact, just reordered in the view
74
+ - Shared results area unchanged
75
+ - AI features unchanged
76
+ - Authentication unchanged
77
+
78
+ ## Files Affected
79
+
80
+ - `app/views/mysql_genius/queries/index.html.erb` -- tab bar reorder, new dashboard partial render, merge visual/sql tabs, JS changes for dashboard auto-load and query explorer toggle
81
+ - `app/views/mysql_genius/queries/_tab_dashboard.html.erb` -- new partial
82
+ - `app/views/mysql_genius/queries/_tab_query_explorer.html.erb` -- new partial combining visual builder and sql query content
83
+ - `app/views/mysql_genius/queries/_tab_visual_builder.html.erb` -- removed (content moves to query explorer)
84
+ - `app/views/mysql_genius/queries/_tab_sql_query.html.erb` -- removed (content moves to query explorer)
85
+ - `app/controllers/concerns/mysql_genius/database_analysis.rb` -- add `limit` param to `query_stats`
86
+ - `mysql_genius.gemspec` -- updated description
87
+ - `README.md` -- updated screenshots order, usage section
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MysqlGenius
4
+ module Generators
5
+ class InstallGenerator < Rails::Generators::Base
6
+ source_root File.expand_path("templates", __dir__)
7
+
8
+ desc "Creates a MysqlGenius initializer and mounts the engine in routes."
9
+
10
+ def copy_initializer
11
+ template("initializer.rb", "config/initializers/mysql_genius.rb")
12
+ end
13
+
14
+ def mount_engine
15
+ route('mount MysqlGenius::Engine, at: "/mysql_genius"')
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,56 @@
1
+ # frozen_string_literal: true
2
+
3
+ MysqlGenius.configure do |config|
4
+ # --- Authentication ---
5
+ # Lambda that receives the controller instance. Return true to allow access.
6
+ # Default: allows everyone. Use route constraints for most cases.
7
+ # config.authenticate = ->(controller) { controller.current_user&.admin? }
8
+
9
+ # To use current_user or other app helpers, inherit from ApplicationController:
10
+ # config.base_controller = "ApplicationController"
11
+
12
+ # --- Tables ---
13
+ # Tables featured at the top of the visual builder dropdown (optional).
14
+ # config.featured_tables = %w[users posts comments]
15
+
16
+ # Tables blocked from querying (defaults: sessions, schema_migrations, ar_internal_metadata).
17
+ # config.blocked_tables += %w[oauth_tokens api_keys]
18
+
19
+ # Column patterns to redact with [REDACTED] in results (case-insensitive substring match).
20
+ # config.masked_column_patterns = %w[password secret digest token ssn]
21
+
22
+ # Default columns checked in the visual builder per table (optional).
23
+ # config.default_columns = {
24
+ # "users" => %w[id name email created_at],
25
+ # "posts" => %w[id title user_id published_at]
26
+ # }
27
+
28
+ # --- Query Safety ---
29
+ # config.max_row_limit = 1000 # Hard cap on rows returned
30
+ # config.default_row_limit = 25 # Default when no limit specified
31
+ # config.query_timeout_ms = 30_000 # 30 second timeout
32
+
33
+ # --- Slow Query Monitoring ---
34
+ # Requires Redis. Set to nil to disable.
35
+ # config.redis_url = ENV["REDIS_URL"]
36
+ # config.slow_query_threshold_ms = 250
37
+
38
+ # --- Audit Logging ---
39
+ # Set to nil to disable. Logs query executions, rejections, and errors.
40
+ # config.audit_logger = Logger.new(Rails.root.join("log", "mysql_genius.log"))
41
+
42
+ # --- AI Features (optional) ---
43
+ # Supports any OpenAI-compatible API: OpenAI, Azure OpenAI, Ollama, or a custom client.
44
+ # config.ai_endpoint = "https://api.openai.com/v1/chat/completions"
45
+ # config.ai_api_key = ENV["OPENAI_API_KEY"]
46
+ # config.ai_model = "gpt-4o"
47
+ # config.ai_auth_style = :bearer # :bearer for OpenAI/Ollama, :api_key for Azure
48
+
49
+ # Domain context helps the AI understand your schema and generate better queries.
50
+ # config.ai_system_context = <<~CONTEXT
51
+ # This is an e-commerce database.
52
+ # - `users` stores customer accounts.
53
+ # - `orders` tracks purchases, linked to users via `user_id`.
54
+ # - Soft-deleted records have `deleted_at IS NOT NULL`.
55
+ # CONTEXT
56
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module MysqlGenius
2
4
  class Configuration
3
5
  # Tables to feature in the visual builder dropdown (array of strings).
@@ -66,17 +68,17 @@ module MysqlGenius
66
68
 
67
69
  def initialize
68
70
  @featured_tables = []
69
- @blocked_tables = %w[
70
- sessions
71
- ar_internal_metadata
72
- schema_migrations
71
+ @blocked_tables = [
72
+ "sessions",
73
+ "ar_internal_metadata",
74
+ "schema_migrations",
73
75
  ]
74
- @masked_column_patterns = %w[password secret digest token]
76
+ @masked_column_patterns = ["password", "secret", "digest", "token"]
75
77
  @default_columns = {}
76
78
  @max_row_limit = 1000
77
79
  @default_row_limit = 25
78
80
  @query_timeout_ms = 30_000
79
- @authenticate = ->(controller) { true }
81
+ @authenticate = ->(_controller) { true }
80
82
  @ai_client = nil
81
83
  @ai_endpoint = nil
82
84
  @ai_api_key = nil
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module MysqlGenius
2
4
  class Engine < ::Rails::Engine
3
5
  isolate_namespace MysqlGenius
@@ -1,36 +1,41 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "json"
4
+ require "time"
2
5
 
3
6
  module MysqlGenius
4
7
  class SlowQueryMonitor
5
- def self.redis_key
6
- "mysql_genius:slow_queries"
7
- end
8
+ class << self
9
+ def redis_key
10
+ "mysql_genius:slow_queries"
11
+ end
8
12
 
9
- def self.subscribe!
10
- ActiveSupport::Notifications.subscribe("sql.active_record") do |_name, start, finish, _id, payload|
11
- duration_ms = ((finish - start) * 1000).round(1)
12
- sql = payload[:sql].to_s
13
- threshold = MysqlGenius.configuration.slow_query_threshold_ms
13
+ def subscribe!
14
+ ActiveSupport::Notifications.subscribe("sql.active_record") do |_name, start, finish, _id, payload|
15
+ duration_ms = ((finish - start) * 1000).round(1)
16
+ sql = payload[:sql].to_s
17
+ threshold = MysqlGenius.configuration.slow_query_threshold_ms
14
18
 
15
- next unless duration_ms >= threshold
16
- next unless sql.match?(/\ASELECT\b/i)
17
- next if sql.include?("SCHEMA")
18
- next if sql.include?("EXPLAIN")
19
- next if payload[:name] == "SCHEMA"
19
+ next if duration_ms < threshold
20
+ next unless sql.match?(/\ASELECT\b/i)
21
+ next if sql.include?("SCHEMA")
22
+ next if sql.include?("EXPLAIN")
23
+ next if payload[:name] == "SCHEMA"
20
24
 
21
- begin
22
- redis = Redis.new(url: MysqlGenius.configuration.redis_url)
23
- entry = {
24
- sql: sql.truncate(10_000),
25
- duration_ms: duration_ms,
26
- timestamp: Time.current.iso8601,
27
- name: payload[:name]
28
- }.to_json
25
+ begin
26
+ redis = Redis.new(url: MysqlGenius.configuration.redis_url)
27
+ entry = {
28
+ sql: sql.length > 10_000 ? sql[0, 10_000] : sql,
29
+ duration_ms: duration_ms,
30
+ timestamp: Time.now.iso8601,
31
+ name: payload[:name],
32
+ }.to_json
29
33
 
30
- redis.lpush(redis_key, entry)
31
- redis.ltrim(redis_key, 0, 199)
32
- rescue => e
33
- Rails.logger.debug("[mysql_genius] Slow query logger error: #{e.message}") if defined?(Rails)
34
+ redis.lpush(redis_key, entry)
35
+ redis.ltrim(redis_key, 0, 199)
36
+ rescue => e
37
+ Rails.logger.debug("[mysql_genius] Slow query logger error: #{e.message}") if defined?(Rails)
38
+ end
34
39
  end
35
40
  end
36
41
  end
@@ -1,8 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module MysqlGenius
2
4
  module SqlValidator
3
- FORBIDDEN_KEYWORDS = %w[INSERT UPDATE DELETE DROP ALTER CREATE TRUNCATE GRANT REVOKE].freeze
5
+ FORBIDDEN_KEYWORDS = ["INSERT", "UPDATE", "DELETE", "DROP", "ALTER", "CREATE", "TRUNCATE", "GRANT", "REVOKE"].freeze
4
6
 
5
- module_function
7
+ extend self
6
8
 
7
9
  def validate(sql, blocked_tables:, connection:)
8
10
  return "Please enter a query." if sql.nil? || sql.strip.empty?
@@ -22,7 +24,7 @@ module MysqlGenius
22
24
  tables_in_query = extract_table_references(normalized, connection)
23
25
  blocked = tables_in_query & blocked_tables
24
26
  if blocked.any?
25
- return "Access denied for table(s): #{blocked.join(', ')}."
27
+ return "Access denied for table(s): #{blocked.join(", ")}."
26
28
  end
27
29
 
28
30
  nil
@@ -44,7 +46,7 @@ module MysqlGenius
44
46
  elsif sql.match?(/\bLIMIT\s+\d+/i)
45
47
  sql.gsub(/\bLIMIT\s+(\d+)/i) { "LIMIT #{[::Regexp.last_match(1).to_i, limit].min}" }
46
48
  else
47
- "#{sql.gsub(/;\s*\z/, '')} LIMIT #{limit}"
49
+ "#{sql.gsub(/;\s*\z/, "")} LIMIT #{limit}"
48
50
  end
49
51
  end
50
52
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module MysqlGenius
2
- VERSION = "0.1.0"
4
+ VERSION = "0.3.0"
3
5
  end
data/lib/mysql_genius.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "mysql_genius/version"
2
4
  require "mysql_genius/configuration"
3
5
  require "mysql_genius/sql_validator"
data/mysql_genius.gemspec CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  lib = File.expand_path("../lib", __FILE__)
2
4
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
5
  require "mysql_genius/version"
@@ -9,9 +11,9 @@ Gem::Specification.new do |spec|
9
11
  spec.email = ["antarr.t.byrd@uth.tmc.edu"]
10
12
 
11
13
  spec.summary = "A MySQL performance dashboard and query explorer for Rails — like PgHero, but for MySQL."
12
- spec.description = "MysqlGenius gives Rails apps a mountable admin dashboard for MySQL databases. " \
13
- "Includes a safe SQL query explorer with visual builder, EXPLAIN analysis, " \
14
- "slow query monitoring, audit logging, and optional AI-powered query suggestions and optimization."
14
+ spec.description = "MysqlGenius gives Rails apps a mountable performance dashboard for MySQL databases. " \
15
+ "Monitor slow queries, analyze query statistics from performance_schema, detect unused and duplicate indexes, " \
16
+ "and explore your database with optional AI-powered optimization."
15
17
  spec.homepage = "https://github.com/antarr/mysql_genius"
16
18
  spec.license = "MIT"
17
19
 
@@ -21,14 +23,13 @@ Gem::Specification.new do |spec|
21
23
  spec.metadata["source_code_uri"] = spec.homepage
22
24
  spec.metadata["changelog_uri"] = "#{spec.homepage}/blob/main/CHANGELOG.md"
23
25
 
24
- spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
25
- `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
26
+ spec.files = Dir.chdir(File.expand_path("..", __FILE__)) do
27
+ %x(git ls-files -z).split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
26
28
  end
27
29
  spec.bindir = "exe"
28
30
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
29
31
  spec.require_paths = ["lib"]
30
32
 
31
- spec.add_dependency "railties", ">= 5.2"
32
- spec.add_dependency "activerecord", ">= 5.2"
33
-
33
+ spec.add_dependency("activerecord", ">= 5.2", "< 9")
34
+ spec.add_dependency("railties", ">= 5.2", "< 9")
34
35
  end
metadata CHANGED
@@ -1,22 +1,24 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mysql_genius
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Antarr Byrd
8
- autorequire:
9
8
  bindir: exe
10
9
  cert_chain: []
11
- date: 2026-04-09 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
12
11
  dependencies:
13
12
  - !ruby/object:Gem::Dependency
14
- name: railties
13
+ name: activerecord
15
14
  requirement: !ruby/object:Gem::Requirement
16
15
  requirements:
17
16
  - - ">="
18
17
  - !ruby/object:Gem::Version
19
18
  version: '5.2'
19
+ - - "<"
20
+ - !ruby/object:Gem::Version
21
+ version: '9'
20
22
  type: :runtime
21
23
  prerelease: false
22
24
  version_requirements: !ruby/object:Gem::Requirement
@@ -24,13 +26,19 @@ dependencies:
24
26
  - - ">="
25
27
  - !ruby/object:Gem::Version
26
28
  version: '5.2'
29
+ - - "<"
30
+ - !ruby/object:Gem::Version
31
+ version: '9'
27
32
  - !ruby/object:Gem::Dependency
28
- name: activerecord
33
+ name: railties
29
34
  requirement: !ruby/object:Gem::Requirement
30
35
  requirements:
31
36
  - - ">="
32
37
  - !ruby/object:Gem::Version
33
38
  version: '5.2'
39
+ - - "<"
40
+ - !ruby/object:Gem::Version
41
+ version: '9'
34
42
  type: :runtime
35
43
  prerelease: false
36
44
  version_requirements: !ruby/object:Gem::Requirement
@@ -38,18 +46,24 @@ dependencies:
38
46
  - - ">="
39
47
  - !ruby/object:Gem::Version
40
48
  version: '5.2'
41
- description: MysqlGenius gives Rails apps a mountable admin dashboard for MySQL databases.
42
- Includes a safe SQL query explorer with visual builder, EXPLAIN analysis, slow query
43
- monitoring, audit logging, and optional AI-powered query suggestions and optimization.
49
+ - - "<"
50
+ - !ruby/object:Gem::Version
51
+ version: '9'
52
+ description: MysqlGenius gives Rails apps a mountable performance dashboard for MySQL
53
+ databases. Monitor slow queries, analyze query statistics from performance_schema,
54
+ detect unused and duplicate indexes, and explore your database with optional AI-powered
55
+ optimization.
44
56
  email:
45
57
  - antarr.t.byrd@uth.tmc.edu
46
58
  executables: []
47
59
  extensions: []
48
60
  extra_rdoc_files: []
49
61
  files:
62
+ - ".github/FUNDING.yml"
50
63
  - ".github/workflows/ci.yml"
51
64
  - ".gitignore"
52
65
  - ".rspec"
66
+ - ".rubocop.yml"
53
67
  - CHANGELOG.md
54
68
  - Gemfile
55
69
  - LICENSE.txt
@@ -66,25 +80,29 @@ files:
66
80
  - app/views/layouts/mysql_genius/application.html.erb
67
81
  - app/views/mysql_genius/queries/_shared_results.html.erb
68
82
  - app/views/mysql_genius/queries/_tab_ai_tools.html.erb
83
+ - app/views/mysql_genius/queries/_tab_dashboard.html.erb
69
84
  - app/views/mysql_genius/queries/_tab_duplicate_indexes.html.erb
85
+ - app/views/mysql_genius/queries/_tab_query_explorer.html.erb
70
86
  - app/views/mysql_genius/queries/_tab_query_stats.html.erb
71
87
  - app/views/mysql_genius/queries/_tab_server.html.erb
72
88
  - app/views/mysql_genius/queries/_tab_slow_queries.html.erb
73
- - app/views/mysql_genius/queries/_tab_sql_query.html.erb
74
89
  - app/views/mysql_genius/queries/_tab_table_sizes.html.erb
75
90
  - app/views/mysql_genius/queries/_tab_unused_indexes.html.erb
76
- - app/views/mysql_genius/queries/_tab_visual_builder.html.erb
77
91
  - app/views/mysql_genius/queries/index.html.erb
78
92
  - bin/console
79
93
  - bin/setup
80
94
  - config/routes.rb
81
95
  - docs/screenshots/ai_tools.png
96
+ - docs/screenshots/dashboard.png
82
97
  - docs/screenshots/duplicate_indexes.png
98
+ - docs/screenshots/query_explore.png
83
99
  - docs/screenshots/query_stats.png
84
100
  - docs/screenshots/server.png
85
- - docs/screenshots/sql_query.png
86
101
  - docs/screenshots/table_sizes.png
87
- - docs/screenshots/visual_builder.png
102
+ - docs/superpowers/plans/2026-04-08-dashboard-first-redesign.md
103
+ - docs/superpowers/specs/2026-04-08-dashboard-first-redesign.md
104
+ - lib/generators/mysql_genius/install/install_generator.rb
105
+ - lib/generators/mysql_genius/install/templates/initializer.rb
88
106
  - lib/mysql_genius.rb
89
107
  - lib/mysql_genius/configuration.rb
90
108
  - lib/mysql_genius/engine.rb
@@ -99,7 +117,6 @@ metadata:
99
117
  homepage_uri: https://github.com/antarr/mysql_genius
100
118
  source_code_uri: https://github.com/antarr/mysql_genius
101
119
  changelog_uri: https://github.com/antarr/mysql_genius/blob/main/CHANGELOG.md
102
- post_install_message:
103
120
  rdoc_options: []
104
121
  require_paths:
105
122
  - lib
@@ -114,8 +131,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
114
131
  - !ruby/object:Gem::Version
115
132
  version: '0'
116
133
  requirements: []
117
- rubygems_version: 3.0.3.1
118
- signing_key:
134
+ rubygems_version: 4.0.4
119
135
  specification_version: 4
120
136
  summary: A MySQL performance dashboard and query explorer for Rails — like PgHero,
121
137
  but for MySQL.
@@ -1,40 +0,0 @@
1
- <!-- SQL Query Tab -->
2
- <div class="mg-tab-content" id="tab-sql">
3
- <% if @ai_enabled %>
4
- <div class="mg-card mg-mb">
5
- <div class="mg-card-header">
6
- <span class="mg-card-toggle" id="ai-toggle">&#9889; AI Assistant <span class="mg-text-muted">- Describe what you want in plain English</span></span>
7
- </div>
8
- <div class="mg-card-body mg-hidden" id="ai-panel">
9
- <div class="mg-field">
10
- <textarea id="ai-prompt" rows="2" placeholder="e.g. Show me all users created in the last 30 days"></textarea>
11
- <div class="mg-text-muted" style="margin-top:2px;">Only table names and column names are sent to the AI. No row data leaves the system.</div>
12
- </div>
13
- <button id="ai-suggest" class="mg-btn mg-btn-primary mg-btn-sm mg-mb">&#9889; Suggest Query</button>
14
- <div id="ai-result" class="mg-hidden">
15
- <div id="ai-explanation" class="mg-alert mg-alert-info"></div>
16
- </div>
17
- </div>
18
- </div>
19
- <% end %>
20
-
21
- <div class="mg-field">
22
- <label for="sql-input">SQL Query</label>
23
- <textarea id="sql-input" rows="5" placeholder="SELECT * FROM users LIMIT 10"></textarea>
24
- </div>
25
- <div class="mg-row">
26
- <div class="mg-col-2 mg-field">
27
- <label for="sql-row-limit">Row Limit</label>
28
- <input type="number" id="sql-row-limit" value="25" min="1" max="<%= MysqlGenius.configuration.max_row_limit %>">
29
- </div>
30
- <div class="mg-field">
31
- <label>&nbsp;</label>
32
- <button id="sql-run" class="mg-btn mg-btn-primary">&#9654; Run Query</button>
33
- <button id="sql-explain" class="mg-btn mg-btn-outline">&#128270; Explain</button>
34
- <% if @ai_enabled %>
35
- <button id="sql-describe" class="mg-btn mg-btn-outline mg-btn-sm" style="margin-left:8px;">&#9889; Describe</button>
36
- <button id="sql-rewrite" class="mg-btn mg-btn-outline mg-btn-sm">&#9889; Rewrite</button>
37
- <% end %>
38
- </div>
39
- </div>
40
- </div>
@@ -1,61 +0,0 @@
1
- <!-- Visual Builder Tab -->
2
- <div class="mg-tab-content active" id="tab-visual">
3
- <div class="mg-row mg-mb">
4
- <div class="mg-col-4 mg-field">
5
- <label for="vb-table">Table</label>
6
- <select id="vb-table">
7
- <option value="">-- Select a table --</option>
8
- <% if @featured_tables != @all_tables %>
9
- <optgroup label="Featured">
10
- <% @featured_tables.each do |table| %>
11
- <option value="<%= table %>"><%= table %></option>
12
- <% end %>
13
- </optgroup>
14
- <optgroup label="All Tables">
15
- <% (@all_tables - @featured_tables).each do |table| %>
16
- <option value="<%= table %>"><%= table %></option>
17
- <% end %>
18
- </optgroup>
19
- <% else %>
20
- <% @all_tables.each do |table| %>
21
- <option value="<%= table %>"><%= table %></option>
22
- <% end %>
23
- <% end %>
24
- </select>
25
- </div>
26
- <div class="mg-col-2 mg-field">
27
- <label for="vb-row-limit">Row Limit</label>
28
- <input type="number" id="vb-row-limit" value="25" min="1" max="<%= MysqlGenius.configuration.max_row_limit %>">
29
- </div>
30
- <div class="mg-field">
31
- <label>&nbsp;</label>
32
- <button id="vb-run" class="mg-btn mg-btn-primary" disabled>&#9654; Run Query</button>
33
- <button id="vb-explain" class="mg-btn mg-btn-outline" disabled>&#128270; Explain</button>
34
- </div>
35
- </div>
36
-
37
- <div id="vb-columns-section" class="mg-mb mg-hidden">
38
- <label>Columns
39
- <span id="vb-toggle-all" class="mg-link">Toggle All</span>
40
- <span id="vb-show-defaults" class="mg-link">Reset Defaults</span>
41
- </label>
42
- <div id="vb-columns" class="mg-checks"></div>
43
- </div>
44
-
45
- <div id="vb-filters-section" class="mg-mb mg-hidden">
46
- <label>Filters</label>
47
- <div id="vb-filters"></div>
48
- <button id="vb-add-filter" class="mg-btn mg-btn-outline-secondary mg-btn-sm" style="margin-top:4px;">+ Add Filter</button>
49
- </div>
50
-
51
- <div id="vb-order-section" class="mg-mb mg-hidden">
52
- <label>Order By</label>
53
- <div id="vb-orders"></div>
54
- <button id="vb-add-order" class="mg-btn mg-btn-outline-secondary mg-btn-sm" style="margin-top:4px;">+ Add Sort</button>
55
- </div>
56
-
57
- <div id="vb-generated-sql" class="mg-mb mg-hidden">
58
- <label>Generated SQL</label>
59
- <textarea id="vb-sql-preview" rows="2" readonly></textarea>
60
- </div>
61
- </div>
Binary file
Binary file