admin_tools 0.1.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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 2efcc50b8fc94f674ff737feb0f4d1150151cdd23cfaa2cc5b6199ebba6eb286
4
+ data.tar.gz: 68d78fae2bbffa56d257ed02758eb09261aa3e25e5fdce652d0653c9c34e5a88
5
+ SHA512:
6
+ metadata.gz: 5abb8c068293a5b09e043f728a752cffb0739ad71fe239cafeefbf30f12215db7777abe710e2407877139c60bc74cc6f4a101afbef9fccf43b1bc163f7af025a
7
+ data.tar.gz: 1c85c8e1ada5d090635a1b3c142bd13c35c405de2b129415dd5a19ff27d95c89a315183a9097bbf8f1a7679eda3e1e8ce6e421eab486f6eb868101a9f7e8ffb9
data/CHANGELOG.md ADDED
@@ -0,0 +1,20 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [Unreleased]
9
+
10
+ ## [0.1.0] - 2025-11-26
11
+
12
+ ### Added
13
+
14
+ - Initial release
15
+ - `admin_tool` helper for wrapping admin-only content
16
+ - `admin_tool_if` helper for conditional admin content
17
+ - `admin_tools_visible?` helper for checking admin status
18
+ - Configurable current user method, admin check method, CSS class, and wrapper element
19
+ - Install generator with optional CSS generation
20
+ - Tailwind CSS support
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2025 Jasper
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,193 @@
1
+ # AdminTools
2
+
3
+ A lightweight Rails gem for conditionally rendering admin-only content in views. Wrap any content in an `admin_tool` block and it only renders for admin users.
4
+
5
+ Inspired by [HCB's admin tools pattern](https://github.com/hackclub/hcb).
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ ```ruby
12
+ gem "admin_tools"
13
+ ```
14
+
15
+ And then execute:
16
+
17
+ ```bash
18
+ bundle install
19
+ rails generate admin_tools:install
20
+ ```
21
+
22
+ ## Usage
23
+
24
+ ### Basic Usage
25
+
26
+ Use the `admin_tool` helper in your views to wrap content that should only be visible to admins:
27
+
28
+ ```erb
29
+ <% admin_tool do %>
30
+ <%= link_to "Edit", edit_admin_path(@resource) %>
31
+ <%= button_to "Delete", @resource, method: :delete %>
32
+ <% end %>
33
+ ```
34
+
35
+ Non-admin users see nothing. Admin users see the content wrapped in a `<div class="admin-tools">`.
36
+
37
+ ### With CSS Classes
38
+
39
+ Pass additional CSS classes (great for Tailwind):
40
+
41
+ ```erb
42
+ <% admin_tool("w-fit bg-red-50 p-2 rounded") do %>
43
+ <p>Admin-only debugging info: <%= @resource.inspect %></p>
44
+ <% end %>
45
+ ```
46
+
47
+ ### Different Wrapper Element
48
+
49
+ Change the wrapper element type:
50
+
51
+ ```erb
52
+ <% admin_tool("inline-flex gap-2", :span) do %>
53
+ <span>Admin badge</span>
54
+ <% end %>
55
+ ```
56
+
57
+ ### With HTML Attributes
58
+
59
+ Pass additional HTML attributes:
60
+
61
+ ```erb
62
+ <% admin_tool("", :div, data: { controller: "admin-panel" }, id: "admin-tools") do %>
63
+ <%= render "admin/quick_actions" %>
64
+ <% end %>
65
+ ```
66
+
67
+ ### Conditional Admin Content
68
+
69
+ Use `admin_tool_if` when you want content visible to everyone OR just admins based on a condition:
70
+
71
+ ```erb
72
+ <%# Show unpublish button only to admins when post is published %>
73
+ <% admin_tool_if(@post.published?) do %>
74
+ <%= link_to "Unpublish", unpublish_path(@post) %>
75
+ <% end %>
76
+ ```
77
+
78
+ When the condition is `false`, content shows to everyone. When `true`, only admins see it.
79
+
80
+ ### Check Admin Visibility
81
+
82
+ You can also check visibility directly:
83
+
84
+ ```erb
85
+ <% if admin_tools_visible? %>
86
+ <p>You're an admin!</p>
87
+ <% end %>
88
+ ```
89
+
90
+ ## Configuration
91
+
92
+ Run the generator to create an initializer:
93
+
94
+ ```bash
95
+ rails generate admin_tools:install
96
+ ```
97
+
98
+ Then customize `config/initializers/admin_tools.rb`:
99
+
100
+ ```ruby
101
+ AdminTools.configure do |config|
102
+ # Method to call to get the current user (default: :current_user)
103
+ config.current_user_method = :current_user
104
+
105
+ # Method to call on the user to check if they're an admin (default: :admin?)
106
+ config.admin_method = :admin?
107
+
108
+ # CSS class applied to all admin_tool wrappers (default: "admin-tools")
109
+ config.css_class = "admin-tools"
110
+
111
+ # Default HTML element for wrapping content (default: :div)
112
+ config.wrapper_element = :div
113
+ end
114
+ ```
115
+
116
+ ### Examples
117
+
118
+ **Using Devise with a `role` column:**
119
+
120
+ ```ruby
121
+ config.current_user_method = :current_user
122
+ config.admin_method = :admin? # assumes User#admin? exists
123
+ ```
124
+
125
+ **Using a different auth system:**
126
+
127
+ ```ruby
128
+ config.current_user_method = :authenticated_user
129
+ config.admin_method = :has_admin_role?
130
+ ```
131
+
132
+ **Using Pundit or similar:**
133
+
134
+ ```ruby
135
+ # In your ApplicationController
136
+ def admin_user?
137
+ current_user&.admin? || policy(current_user).admin?
138
+ end
139
+ helper_method :admin_user?
140
+
141
+ # In initializer - call a helper method instead
142
+ config.admin_method = :itself # Always returns truthy for non-nil users
143
+ # Then override admin_tools_visible? in ApplicationHelper:
144
+ #
145
+ # def admin_tools_visible?
146
+ # admin_user?
147
+ # end
148
+ ```
149
+
150
+ ## Styling
151
+
152
+ Generate optional CSS to visually distinguish admin tools:
153
+
154
+ ```bash
155
+ # Standard CSS
156
+ rails generate admin_tools:install --css
157
+
158
+ # Tailwind CSS
159
+ rails generate admin_tools:install --css --tailwind
160
+ ```
161
+
162
+ This creates `app/assets/stylesheets/admin_tools.css` with a dashed red border and "Admin" label. Customize or remove in production as needed.
163
+
164
+ ## Requirements
165
+
166
+ - Rails >= 6.1
167
+ - Ruby >= 3.0
168
+ - A `current_user` method (or configured equivalent) that returns the logged-in user
169
+ - An `admin?` method (or configured equivalent) on your User model
170
+
171
+ ## Development
172
+
173
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests.
174
+
175
+ ## Releasing
176
+
177
+ 1. Update the version in `lib/admin_tools/version.rb`
178
+ 2. Update `CHANGELOG.md`
179
+ 3. Commit: `git commit -am "Release vX.X.X"`
180
+ 4. Tag: `git tag vX.X.X`
181
+ 5. Push: `git push origin main --tags`
182
+
183
+ The GitHub Action will automatically publish to RubyGems.org.
184
+
185
+ > **Note:** You need to configure [Trusted Publishing](https://guides.rubygems.org/trusted-publishing/) on RubyGems.org and create a `release` environment in your GitHub repo settings.
186
+
187
+ ## Contributing
188
+
189
+ Bug reports and pull requests are welcome on GitHub.
190
+
191
+ ## License
192
+
193
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/gem_tasks"
4
+ require "rspec/core/rake_task"
5
+
6
+ RSpec::Core::RakeTask.new(:spec)
7
+
8
+ task default: :spec
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "lib/admin_tools/version"
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = "admin_tools"
7
+ spec.version = AdminTools::VERSION
8
+ spec.authors = ["Jasper Mayone"]
9
+ spec.email = ["me@jaspermayone.com"]
10
+
11
+ spec.summary = "Simple admin-only content helpers for Rails views"
12
+ spec.description = "A lightweight Rails helper for conditionally rendering admin-only content in views. Wrap any content in an admin_tool block and it only renders for admin users."
13
+ spec.homepage = "https://github.com/jasper/admin_tools"
14
+ spec.license = "MIT"
15
+ spec.required_ruby_version = ">= 3.0.0"
16
+
17
+ spec.metadata["homepage_uri"] = spec.homepage
18
+ spec.metadata["source_code_uri"] = spec.homepage
19
+ spec.metadata["changelog_uri"] = "#{spec.homepage}/blob/main/CHANGELOG.md"
20
+
21
+ spec.files = Dir.chdir(__dir__) do
22
+ `git ls-files -z`.split("\x0").reject do |f|
23
+ (File.expand_path(f) == __FILE__) ||
24
+ f.start_with?(*%w[bin/ test/ spec/ features/ .git .github appveyor Gemfile])
25
+ end
26
+ end
27
+ spec.bindir = "exe"
28
+ spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
29
+ spec.require_paths = ["lib"]
30
+
31
+ spec.add_dependency "rails", ">= 6.1"
32
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ module AdminTools
4
+ class Configuration
5
+ attr_accessor :current_user_method, :admin_method, :css_class, :wrapper_element
6
+
7
+ def initialize
8
+ @current_user_method = :current_user
9
+ @admin_method = :admin?
10
+ @css_class = "admin-tools"
11
+ @wrapper_element = :div
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,75 @@
1
+ # frozen_string_literal: true
2
+
3
+ module AdminTools
4
+ module Helper
5
+ # Renders content only for admin users
6
+ #
7
+ # @param class_name [String] Additional CSS classes to add to the wrapper
8
+ # @param element [Symbol, String] HTML element to wrap content in (default: configured wrapper_element)
9
+ # @param options [Hash] Additional HTML attributes for the wrapper element
10
+ # @yield Block containing the content to render for admins
11
+ #
12
+ # @example Basic usage
13
+ # <% admin_tool do %>
14
+ # <%= link_to "Delete", resource_path, method: :delete %>
15
+ # <% end %>
16
+ #
17
+ # @example With CSS classes
18
+ # <% admin_tool("w-fit bg-red-50 p-2") do %>
19
+ # <p>Admin-only content</p>
20
+ # <% end %>
21
+ #
22
+ # @example With different wrapper element
23
+ # <% admin_tool("inline-flex", :span) do %>
24
+ # Admin badge
25
+ # <% end %>
26
+ #
27
+ # @example With HTML attributes
28
+ # <% admin_tool("", :div, data: { controller: "admin" }) do %>
29
+ # <%= render "admin/panel" %>
30
+ # <% end %>
31
+ #
32
+ def admin_tool(class_name = "", element = nil, **options, &block)
33
+ return unless admin_tools_visible?
34
+
35
+ element ||= AdminTools.configuration.wrapper_element
36
+ css_classes = [AdminTools.configuration.css_class, class_name].reject(&:blank?).join(" ")
37
+
38
+ concat content_tag(element, class: css_classes, **options, &block)
39
+ end
40
+
41
+ # Conditionally renders content for admins only based on a condition
42
+ #
43
+ # If condition is false, content is shown to ALL users.
44
+ # If condition is true, content is only shown to admins.
45
+ #
46
+ # @param condition [Boolean] When true, restrict to admins only
47
+ # @param args [Array] Arguments passed to admin_tool
48
+ # @param options [Hash] Options passed to admin_tool
49
+ # @yield Block containing the content
50
+ #
51
+ # @example Show draft badge to everyone, but admin actions only to admins
52
+ # <% admin_tool_if(@post.published?) do %>
53
+ # <%= link_to "Unpublish", unpublish_path(@post) %>
54
+ # <% end %>
55
+ #
56
+ def admin_tool_if(condition, *args, **options, &block)
57
+ yield and return unless condition
58
+
59
+ admin_tool(*args, **options, &block)
60
+ end
61
+
62
+ # Returns whether admin tools should be visible to the current user
63
+ #
64
+ # @return [Boolean]
65
+ #
66
+ def admin_tools_visible?
67
+ user = send(AdminTools.configuration.current_user_method)
68
+ return false if user.nil?
69
+
70
+ user.send(AdminTools.configuration.admin_method)
71
+ rescue NoMethodError
72
+ false
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module AdminTools
4
+ class Railtie < ::Rails::Railtie
5
+ initializer "admin_tools.helper" do
6
+ ActiveSupport.on_load(:action_view) do
7
+ include AdminTools::Helper
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module AdminTools
4
+ VERSION = "0.1.0"
5
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "admin_tools/version"
4
+ require_relative "admin_tools/configuration"
5
+ require_relative "admin_tools/helper"
6
+ require_relative "admin_tools/railtie" if defined?(Rails::Railtie)
7
+
8
+ module AdminTools
9
+ class << self
10
+ attr_writer :configuration
11
+
12
+ def configuration
13
+ @configuration ||= Configuration.new
14
+ end
15
+
16
+ def configure
17
+ yield(configuration)
18
+ end
19
+
20
+ def reset_configuration!
21
+ @configuration = Configuration.new
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rails/generators/base"
4
+
5
+ module AdminTools
6
+ module Generators
7
+ class InstallGenerator < Rails::Generators::Base
8
+ source_root File.expand_path("templates", __dir__)
9
+
10
+ desc "Creates an AdminTools initializer and optional CSS file"
11
+
12
+ class_option :css, type: :boolean, default: false, desc: "Generate CSS file with default styles"
13
+ class_option :tailwind, type: :boolean, default: false, desc: "Use Tailwind CSS classes in generated CSS"
14
+
15
+ def create_initializer
16
+ template "initializer.rb", "config/initializers/admin_tools.rb"
17
+ end
18
+
19
+ def create_css_file
20
+ return unless options[:css]
21
+
22
+ if options[:tailwind]
23
+ template "admin_tools_tailwind.css", "app/assets/stylesheets/admin_tools.css"
24
+ else
25
+ template "admin_tools.css", "app/assets/stylesheets/admin_tools.css"
26
+ end
27
+ end
28
+
29
+ def show_readme
30
+ readme "README" if behavior == :invoke
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,24 @@
1
+
2
+ ===============================================================================
3
+
4
+ AdminTools has been installed!
5
+
6
+ Next steps:
7
+
8
+ 1. Update config/initializers/admin_tools.rb if you need to customize:
9
+ - The method used to get the current user
10
+ - The method used to check if a user is an admin
11
+ - The default CSS class or wrapper element
12
+
13
+ 2. Use admin_tool in your views:
14
+
15
+ <%% admin_tool do %>
16
+ <%%= link_to "Admin Action", admin_path %>
17
+ <%% end %>
18
+
19
+ 3. (Optional) Add CSS to style admin tools visually:
20
+
21
+ rails generate admin_tools:install --css
22
+ rails generate admin_tools:install --css --tailwind
23
+
24
+ ===============================================================================
@@ -0,0 +1,41 @@
1
+ /*
2
+ * AdminTools default styles
3
+ * These styles help visually distinguish admin-only content during development
4
+ */
5
+
6
+ .admin-tools {
7
+ border: 2px dashed #ec3750;
8
+ background-color: rgba(236, 55, 80, 0.05);
9
+ padding: 0.5rem;
10
+ border-radius: 0.25rem;
11
+ position: relative;
12
+ }
13
+
14
+ /* Optional: Add an "Admin" label */
15
+ .admin-tools::before {
16
+ content: "Admin";
17
+ position: absolute;
18
+ top: -0.75rem;
19
+ left: 0.5rem;
20
+ background-color: #ec3750;
21
+ color: white;
22
+ font-size: 0.625rem;
23
+ font-weight: 600;
24
+ padding: 0.125rem 0.375rem;
25
+ border-radius: 0.25rem;
26
+ text-transform: uppercase;
27
+ letter-spacing: 0.05em;
28
+ }
29
+
30
+ /* Remove visual styling in production if desired */
31
+ /*
32
+ .admin-tools--production {
33
+ border: none;
34
+ background: none;
35
+ padding: 0;
36
+ }
37
+
38
+ .admin-tools--production::before {
39
+ display: none;
40
+ }
41
+ */
@@ -0,0 +1,14 @@
1
+ /*
2
+ * AdminTools Tailwind styles
3
+ * Uses Tailwind's @apply directive for styling
4
+ */
5
+
6
+ .admin-tools {
7
+ @apply border-2 border-dashed border-red-500 bg-red-50/50 p-2 rounded relative;
8
+ }
9
+
10
+ /* Optional: Add an "Admin" label */
11
+ .admin-tools::before {
12
+ content: "Admin";
13
+ @apply absolute -top-2.5 left-2 bg-red-500 text-white text-xs font-semibold px-1.5 py-0.5 rounded uppercase tracking-wide;
14
+ }
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ AdminTools.configure do |config|
4
+ # Method to call to get the current user (default: :current_user)
5
+ # config.current_user_method = :current_user
6
+
7
+ # Method to call on the user to check if they're an admin (default: :admin?)
8
+ # config.admin_method = :admin?
9
+
10
+ # CSS class applied to all admin_tool wrappers (default: "admin-tools")
11
+ # config.css_class = "admin-tools"
12
+
13
+ # Default HTML element for wrapping content (default: :div)
14
+ # config.wrapper_element = :div
15
+ end
metadata ADDED
@@ -0,0 +1,74 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: admin_tools
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Jasper Mayone
8
+ bindir: exe
9
+ cert_chain: []
10
+ date: 1980-01-02 00:00:00.000000000 Z
11
+ dependencies:
12
+ - !ruby/object:Gem::Dependency
13
+ name: rails
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - ">="
17
+ - !ruby/object:Gem::Version
18
+ version: '6.1'
19
+ type: :runtime
20
+ prerelease: false
21
+ version_requirements: !ruby/object:Gem::Requirement
22
+ requirements:
23
+ - - ">="
24
+ - !ruby/object:Gem::Version
25
+ version: '6.1'
26
+ description: A lightweight Rails helper for conditionally rendering admin-only content
27
+ in views. Wrap any content in an admin_tool block and it only renders for admin
28
+ users.
29
+ email:
30
+ - me@jaspermayone.com
31
+ executables: []
32
+ extensions: []
33
+ extra_rdoc_files: []
34
+ files:
35
+ - CHANGELOG.md
36
+ - LICENSE.txt
37
+ - README.md
38
+ - Rakefile
39
+ - admin_tools.gemspec
40
+ - lib/admin_tools.rb
41
+ - lib/admin_tools/configuration.rb
42
+ - lib/admin_tools/helper.rb
43
+ - lib/admin_tools/railtie.rb
44
+ - lib/admin_tools/version.rb
45
+ - lib/generators/admin_tools/install/install_generator.rb
46
+ - lib/generators/admin_tools/install/templates/README
47
+ - lib/generators/admin_tools/install/templates/admin_tools.css
48
+ - lib/generators/admin_tools/install/templates/admin_tools_tailwind.css
49
+ - lib/generators/admin_tools/install/templates/initializer.rb
50
+ homepage: https://github.com/jasper/admin_tools
51
+ licenses:
52
+ - MIT
53
+ metadata:
54
+ homepage_uri: https://github.com/jasper/admin_tools
55
+ source_code_uri: https://github.com/jasper/admin_tools
56
+ changelog_uri: https://github.com/jasper/admin_tools/blob/main/CHANGELOG.md
57
+ rdoc_options: []
58
+ require_paths:
59
+ - lib
60
+ required_ruby_version: !ruby/object:Gem::Requirement
61
+ requirements:
62
+ - - ">="
63
+ - !ruby/object:Gem::Version
64
+ version: 3.0.0
65
+ required_rubygems_version: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - ">="
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ requirements: []
71
+ rubygems_version: 3.7.2
72
+ specification_version: 4
73
+ summary: Simple admin-only content helpers for Rails views
74
+ test_files: []