active_admin_theme 3.1.1 → 3.2.1
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 +4 -4
- data/README.md +185 -34
- data/app/assets/javascripts/wigu/all.js +10 -0
- data/app/assets/javascripts/wigu/scrollbar_width.js +72 -0
- data/app/assets/javascripts/wigu/server_clock.js +171 -0
- data/app/assets/javascripts/wigu/table_crisscross.js +49 -0
- data/app/assets/stylesheets/wigu/active_admin_theme.scss +480 -16
- data/lib/active_admin_theme/version.rb +1 -1
- data/lib/active_admin_theme.rb +127 -1
- metadata +5 -1
data/lib/active_admin_theme.rb
CHANGED
|
@@ -3,6 +3,132 @@ require "active_admin_theme/version"
|
|
|
3
3
|
module ActiveAdminTheme
|
|
4
4
|
module Rails
|
|
5
5
|
class Engine < ::Rails::Engine
|
|
6
|
+
# Register the server clock once AA is available. server_clock.js (shipped
|
|
7
|
+
# in this gem) ticks li#servertime in #utility_nav and reads the server
|
|
8
|
+
# instant from [data-servertime]; here we render both server-side, per
|
|
9
|
+
# namespace, so every consumer gets the clock without reimplementing it.
|
|
10
|
+
# after :load_config_initializers, or hosts loading AA from a config
|
|
11
|
+
# initializer (gem "activeadmin", require: false) fail the defined?
|
|
12
|
+
# check and silently get no clock — engine initializers otherwise run
|
|
13
|
+
# before the host's config/initializers.
|
|
14
|
+
initializer "active_admin_theme.server_clock", after: :load_config_initializers do
|
|
15
|
+
if defined?(::ActiveAdmin)
|
|
16
|
+
ActiveAdminTheme.install!
|
|
17
|
+
else
|
|
18
|
+
# Evaluated once; a host requiring activeadmin even later (routes.rb,
|
|
19
|
+
# an ENV-gated engine) gets no theme at all — say so instead of
|
|
20
|
+
# silently shipping a README-promised feature that never appears.
|
|
21
|
+
::Rails.logger&.warn(
|
|
22
|
+
"active_admin_theme: ActiveAdmin was not loaded when the engine " \
|
|
23
|
+
"initialized; the utility-nav clock and logout handling are " \
|
|
24
|
+
"disabled. Require \"active_admin\" no later than config/initializers."
|
|
25
|
+
)
|
|
26
|
+
end
|
|
27
|
+
end
|
|
6
28
|
end
|
|
7
29
|
end
|
|
8
|
-
|
|
30
|
+
|
|
31
|
+
# Opt-out for the restored current-user item. Unlike logout (which AA turns
|
|
32
|
+
# off per namespace via logout_link_path = nil), AA has no switch short of
|
|
33
|
+
# unsetting current_user_method — which also breaks authorization — and
|
|
34
|
+
# Menu has no removal API, so hosts that deliberately run a user-link-free
|
|
35
|
+
# header (e.g. display_name would leak an email) set this in an initializer:
|
|
36
|
+
# ActiveAdminTheme.add_current_user = false
|
|
37
|
+
class << self
|
|
38
|
+
attr_accessor :add_current_user
|
|
39
|
+
end
|
|
40
|
+
self.add_current_user = true
|
|
41
|
+
|
|
42
|
+
# Add a utility-nav clock item (and ensure a logout item) to every AA namespace.
|
|
43
|
+
#
|
|
44
|
+
# data-servertime must be fresh on every request, but only a menu item's
|
|
45
|
+
# :label/:url/:if are evaluated per request — :html_options is captured once at
|
|
46
|
+
# build time. So the instant is embedded in the label as html_safe markup
|
|
47
|
+
# rather than an html_option. The label is "YYYY MM DD HH MM SS ZONE" (exactly
|
|
48
|
+
# what server_clock.js parses) on an inner span; the JS overwrites the visible
|
|
49
|
+
# text each tick. Timezone comes from the host app's Time.current/Time.zone.
|
|
50
|
+
def self.install!
|
|
51
|
+
# after_load fires on every ActiveAdmin.load! (each dev reload), and each
|
|
52
|
+
# build_menu call registers a before_build callback that MenuCollection#clear!
|
|
53
|
+
# never removes — so register once per namespace or callbacks pile up for
|
|
54
|
+
# the life of the process. Namespace objects and their MenuCollection
|
|
55
|
+
# survive unload! (it only clears the built menus), so once is enough.
|
|
56
|
+
seen = {}.compare_by_identity
|
|
57
|
+
register = lambda do |namespace|
|
|
58
|
+
next if seen[namespace]
|
|
59
|
+
seen[namespace] = true
|
|
60
|
+
namespace.build_menu(:utility_navigation) do |menu|
|
|
61
|
+
# A consumer item with the same id wins, but NOT through these
|
|
62
|
+
# guards: before_build unshifts, so the LAST registration runs
|
|
63
|
+
# first, and consumer hooks (config/initializers) subscribe before
|
|
64
|
+
# this engine's initializer — on a production first load THIS
|
|
65
|
+
# callback runs first against an empty menu and the guards all
|
|
66
|
+
# pass. What protects consumer overrides is Menu#_add replacing by
|
|
67
|
+
# id when their callback runs afterwards. The guards only matter
|
|
68
|
+
# from the second dev reload on, when consumer items are already
|
|
69
|
+
# present — do not tighten them into the primary mechanism.
|
|
70
|
+
unless menu["servertime"]
|
|
71
|
+
menu.add id: "servertime",
|
|
72
|
+
priority: 99_990,
|
|
73
|
+
url: -> {},
|
|
74
|
+
# same guard both default utility items carry — the nav
|
|
75
|
+
# stays empty for anonymous visitors, as it was pre-theme
|
|
76
|
+
if: :current_active_admin_user?,
|
|
77
|
+
label: lambda {
|
|
78
|
+
now = Time.current
|
|
79
|
+
data = now.strftime("%Y %m %d %H %M %S %Z")
|
|
80
|
+
shown = now.strftime("%Y %b %d %H:%M:%S %Z")
|
|
81
|
+
# epoch + IANA zone let the JS re-apply the server
|
|
82
|
+
# zone's offset on every tick (DST included); the
|
|
83
|
+
# wall-clock attribute stays as the documented contract
|
|
84
|
+
# for host-rendered elements and older scripts.
|
|
85
|
+
# Time.zone is nil under Time.use_zone(nil) — the
|
|
86
|
+
# common around_action(user.time_zone) pattern with a
|
|
87
|
+
# nil column — while Time.current still works; skip the
|
|
88
|
+
# precise attributes then instead of 500ing the page.
|
|
89
|
+
tz = Time.zone
|
|
90
|
+
precise = tz ? %( data-servertime-epoch="#{now.to_i}" data-servertime-zone="#{tz.tzinfo.identifier}") : ""
|
|
91
|
+
%(<span data-servertime="#{data}"#{precise}>#{shown}</span>).html_safe
|
|
92
|
+
}
|
|
93
|
+
end
|
|
94
|
+
# Claiming :utility_navigation stops AA's build_default_utility_nav
|
|
95
|
+
# (it returns early once the menu exists), so restore the default
|
|
96
|
+
# current-user item it would have added. No-op when the host has no
|
|
97
|
+
# current_user_method, exactly like the default nav.
|
|
98
|
+
if ActiveAdminTheme.add_current_user && !menu["current_user"]
|
|
99
|
+
namespace.add_current_user_to_menu(menu)
|
|
100
|
+
end
|
|
101
|
+
# Opting out is ActiveAdmin's own per-namespace switch, not a theme
|
|
102
|
+
# flag: config.logout_link_path = nil makes add_logout_button_to_menu
|
|
103
|
+
# a no-op (AA guards on `if logout_link_path`). Hosts with custom
|
|
104
|
+
# auth and no logout route — where rendering the default item would
|
|
105
|
+
# public_send a missing helper and 500 — set exactly that.
|
|
106
|
+
# The wigu-logout class (lands on the <a> — AA passes html_options to
|
|
107
|
+
# link_to) scopes the stylesheet's icon treatment to THIS item, so a
|
|
108
|
+
# consumer-rendered logout with its own label keeps its text. The
|
|
109
|
+
# aria-label is the accessible name: the stylesheet hides the link
|
|
110
|
+
# text with font-size: 0, which some screen readers prune from the
|
|
111
|
+
# accessibility tree. html_options are captured at menu-build time, so
|
|
112
|
+
# the label uses the locale active then — good enough for a nav icon.
|
|
113
|
+
unless menu["logout"]
|
|
114
|
+
namespace.add_logout_button_to_menu(
|
|
115
|
+
menu, 99_999,
|
|
116
|
+
class: "wigu-logout", "aria-label": I18n.t("active_admin.logout")
|
|
117
|
+
)
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
::ActiveAdmin.after_load do |app|
|
|
123
|
+
app.namespaces.each(®ister)
|
|
124
|
+
end
|
|
125
|
+
# Production fires after_load exactly once (load! gates on @@loaded), so a
|
|
126
|
+
# namespace created later — e.g. another engine's later-subscribed hook
|
|
127
|
+
# registering a resource into a new namespace — would keep AA's stock
|
|
128
|
+
# default nav, inconsistently with its siblings. Namespace creation has
|
|
129
|
+
# its own notification; theme late arrivals through it.
|
|
130
|
+
ActiveSupport::Notifications.subscribe(::ActiveAdmin::Namespace::RegisterEvent) do |*args|
|
|
131
|
+
register.call(args.last[:active_admin_namespace])
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: active_admin_theme
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 3.
|
|
4
|
+
version: 3.2.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Igor Fedoronchuk
|
|
@@ -40,6 +40,10 @@ extra_rdoc_files: []
|
|
|
40
40
|
files:
|
|
41
41
|
- LICENSE.txt
|
|
42
42
|
- README.md
|
|
43
|
+
- app/assets/javascripts/wigu/all.js
|
|
44
|
+
- app/assets/javascripts/wigu/scrollbar_width.js
|
|
45
|
+
- app/assets/javascripts/wigu/server_clock.js
|
|
46
|
+
- app/assets/javascripts/wigu/table_crisscross.js
|
|
43
47
|
- app/assets/javascripts/wigu/theme_toggle.js
|
|
44
48
|
- app/assets/stylesheets/wigu/active_admin_theme.scss
|
|
45
49
|
- lib/active_admin_theme.rb
|