karafka-web 0.10.2 → 0.10.4
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
- checksums.yaml.gz.sig +0 -0
- data/CHANGELOG.md +17 -0
- data/Gemfile.lock +12 -10
- data/config/locales/pro_errors.yml +7 -1
- data/docker-compose.yml +1 -1
- data/karafka-web.gemspec +8 -2
- data/lib/karafka/web/config.rb +6 -1
- data/lib/karafka/web/contracts/config.rb +1 -0
- data/lib/karafka/web/management/actions/create_topics.rb +1 -1
- data/lib/karafka/web/pro/commanding/commands/{probe.rb → trace.rb} +3 -3
- data/lib/karafka/web/pro/commanding/listener.rb +1 -1
- data/lib/karafka/web/pro/commanding/manager.rb +2 -2
- data/lib/karafka/web/pro/commanding.rb +1 -1
- data/lib/karafka/web/pro/loader.rb +23 -2
- data/lib/karafka/web/pro/ui/app.rb +12 -2
- data/lib/karafka/web/pro/ui/controllers/commanding_controller.rb +4 -4
- data/lib/karafka/web/pro/ui/controllers/routing_controller.rb +18 -1
- data/lib/karafka/web/pro/ui/controllers/scheduled_messages/messages_controller.rb +60 -0
- data/lib/karafka/web/pro/ui/lib/branding/config.rb +40 -0
- data/lib/karafka/web/pro/ui/lib/branding/contracts/config.rb +56 -0
- data/lib/karafka/web/pro/ui/lib/branding.rb +36 -0
- data/lib/karafka/web/pro/ui/views/commands/_command.erb +1 -1
- data/lib/karafka/web/pro/ui/views/consumers/_consumer_controls.erb +3 -3
- data/lib/karafka/web/pro/ui/views/consumers/consumer/_commands.erb +4 -4
- data/lib/karafka/web/pro/ui/views/recurring_tasks/_actions.erb +2 -2
- data/lib/karafka/web/pro/ui/views/routing/_consumer_group.erb +2 -0
- data/lib/karafka/web/pro/ui/views/routing/_topic.erb +10 -0
- data/lib/karafka/web/pro/ui/views/scheduled_messages/explorer/_key.erb +9 -0
- data/lib/karafka/web/pro/ui/views/scheduled_messages/explorer/_message.erb +51 -13
- data/lib/karafka/web/pro/ui/views/shared/_navigation.erb +20 -15
- data/lib/karafka/web/pro/ui/views/shared/branding/_label.erb +20 -0
- data/lib/karafka/web/pro/ui/views/shared/branding/_notice.erb +13 -0
- data/lib/karafka/web/tracking/consumers/listeners/errors.rb +38 -9
- data/lib/karafka/web/tracking/producers/reporter.rb +1 -8
- data/lib/karafka/web/ui/helpers/tailwind_helper.rb +5 -4
- data/lib/karafka/web/ui/public/javascripts/application.js +1 -0
- data/lib/karafka/web/ui/public/javascripts/application.min.js +4 -3
- data/lib/karafka/web/ui/public/javascripts/application.min.js.br +0 -0
- data/lib/karafka/web/ui/public/javascripts/application.min.js.gz +0 -0
- data/lib/karafka/web/ui/public/javascripts/components/btn_toggle_manager.js +31 -11
- data/lib/karafka/web/ui/public/stylesheets/application.css +21 -0
- data/lib/karafka/web/ui/public/stylesheets/application.min.css +2 -1
- data/lib/karafka/web/ui/public/stylesheets/application.min.css.br +0 -0
- data/lib/karafka/web/ui/public/stylesheets/application.min.css.gz +0 -0
- data/lib/karafka/web/ui/public/stylesheets/libs/tailwind.css +69 -2
- data/lib/karafka/web/ui/views/layout.erb +5 -2
- data/lib/karafka/web/ui/views/shared/_brand.erb +3 -2
- data/lib/karafka/web/ui/views/shared/_navigation.erb +19 -15
- data/lib/karafka/web/ui/views/shared/alerts/_error.erb +3 -1
- data/lib/karafka/web/ui/views/shared/alerts/_info.erb +1 -1
- data/lib/karafka/web/ui/views/shared/alerts/_primary.erb +3 -1
- data/lib/karafka/web/ui/views/shared/alerts/_secondary.erb +3 -1
- data/lib/karafka/web/ui/views/shared/alerts/_success.erb +3 -1
- data/lib/karafka/web/ui/views/shared/alerts/_warning.erb +3 -1
- data/lib/karafka/web/ui/views/shared/icons/_chevron.erb +4 -0
- data/lib/karafka/web/version.rb +1 -1
- data/lib/karafka/web.rb +6 -1
- data/package-lock.json +40 -35
- data.tar.gz.sig +0 -0
- metadata +13 -15
- metadata.gz.sig +0 -0
- data/.coditsu/ci.yml +0 -3
- data/.diffend.yml +0 -3
- data/.github/FUNDING.yml +0 -1
- data/.github/ISSUE_TEMPLATE/bug_report.md +0 -50
- data/.github/ISSUE_TEMPLATE/feature_request.md +0 -20
- data/.github/workflows/ci.yml +0 -133
- data/.gitignore +0 -71
- data/.rspec +0 -1
- data/.ruby-gemset +0 -1
- data/.ruby-version +0 -1
@@ -10,6 +10,7 @@
|
|
10
10
|
<th>Subscription group</th>
|
11
11
|
<th><%== sort_link('Topic', :name) %></th>
|
12
12
|
<th>Type</th>
|
13
|
+
<th>Assigned</th>
|
13
14
|
<th><%== sort_link(:active?) %></th>
|
14
15
|
<th></th>
|
15
16
|
</tr>
|
@@ -21,6 +22,7 @@
|
|
21
22
|
'routing/topic',
|
22
23
|
locals: {
|
23
24
|
subscription_group: topic.subscription_group,
|
25
|
+
consumer_group: consumer_group.id,
|
24
26
|
topic: topic
|
25
27
|
}
|
26
28
|
)
|
@@ -20,6 +20,16 @@
|
|
20
20
|
<% end %>
|
21
21
|
</td>
|
22
22
|
|
23
|
+
<td>
|
24
|
+
<% assigned = @assigned[consumer_group].include?(topic.name) %>
|
25
|
+
|
26
|
+
<% if assigned %>
|
27
|
+
<%== badge_success assigned %>
|
28
|
+
<% else %>
|
29
|
+
<%== badge_secondary assigned %>
|
30
|
+
<% end %>
|
31
|
+
</td>
|
32
|
+
|
23
33
|
<td>
|
24
34
|
<% if topic.active? %>
|
25
35
|
<%== badge_success topic.active? %>
|
@@ -39,8 +39,22 @@
|
|
39
39
|
</td>
|
40
40
|
|
41
41
|
<% if type == 'cancel' %>
|
42
|
-
<td
|
43
|
-
|
42
|
+
<td>
|
43
|
+
<%== relative_time(message.timestamp) %>
|
44
|
+
</td>
|
45
|
+
<td class="text-center text-muted">
|
46
|
+
N/A
|
47
|
+
</td>
|
48
|
+
<td>
|
49
|
+
<%==
|
50
|
+
partial(
|
51
|
+
'scheduled_messages/explorer/key',
|
52
|
+
locals: { message: message, safe_key: safe_key }
|
53
|
+
)
|
54
|
+
%>
|
55
|
+
</td>
|
56
|
+
<td colspan="2" class="text-center text-muted">
|
57
|
+
N/A
|
44
58
|
</td>
|
45
59
|
<% else %>
|
46
60
|
<td>
|
@@ -50,15 +64,12 @@
|
|
50
64
|
<%== relative_time message.headers['schedule_target_epoch'].to_i %>
|
51
65
|
</td>
|
52
66
|
<td>
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
<% else %>
|
60
|
-
<span class="text-muted">[Filtered]</span>
|
61
|
-
<% end %>
|
67
|
+
<%==
|
68
|
+
partial(
|
69
|
+
'scheduled_messages/explorer/key',
|
70
|
+
locals: { message: message, safe_key: safe_key }
|
71
|
+
)
|
72
|
+
%>
|
62
73
|
</td>
|
63
74
|
<td>
|
64
75
|
<%= message.headers['schedule_target_topic'] %>
|
@@ -73,10 +84,37 @@
|
|
73
84
|
<% end %>
|
74
85
|
|
75
86
|
<td>
|
87
|
+
<% if type == 'schedule' %>
|
88
|
+
<%
|
89
|
+
cancel_path = root_path(
|
90
|
+
"scheduled_messages/messages",
|
91
|
+
message.topic,
|
92
|
+
message.partition,
|
93
|
+
message.offset,
|
94
|
+
'cancel'
|
95
|
+
)
|
96
|
+
%>
|
97
|
+
<form
|
98
|
+
action="<%= cancel_path %>"
|
99
|
+
method="post"
|
100
|
+
class="inline"
|
101
|
+
>
|
102
|
+
<%== csrf_tag(cancel_path) %>
|
103
|
+
<button
|
104
|
+
type="submit"
|
105
|
+
class="btn btn-error btn-sm confirm-action"
|
106
|
+
title="Cancel dispatch of this scheduled message"
|
107
|
+
>
|
108
|
+
<%== icon(:x_circle) %>
|
109
|
+
</button>
|
110
|
+
</form>
|
111
|
+
<% end %>
|
112
|
+
|
76
113
|
<%==
|
77
114
|
link_button_primary_sm(
|
78
|
-
|
79
|
-
explorer_path(message.topic, message.partition, message.offset)
|
115
|
+
icon(:info_circle),
|
116
|
+
explorer_path(message.topic, message.partition, message.offset),
|
117
|
+
title: 'Display details of this message'
|
80
118
|
)
|
81
119
|
%>
|
82
120
|
</td>
|
@@ -1,14 +1,15 @@
|
|
1
1
|
<nav class="sidebar-nav">
|
2
2
|
<%== partial 'shared/brand' %>
|
3
|
+
<%== partial 'shared/branding/label' %>
|
3
4
|
|
4
|
-
<ul class="menu">
|
5
|
+
<ul class="menu grow">
|
5
6
|
<li>
|
6
7
|
<a
|
7
8
|
class="sidebar-nav-item <%= nav_class(start_with: '/dashboard') %>"
|
8
9
|
href="<%= root_path('dashboard') %>"
|
9
10
|
>
|
10
11
|
<%== icon(:home) %>
|
11
|
-
Dashboard
|
12
|
+
<span class="sidebar-nav-item-label">Dashboard</span>
|
12
13
|
</a>
|
13
14
|
</li>
|
14
15
|
|
@@ -18,7 +19,7 @@
|
|
18
19
|
href="<%= root_path('consumers') %>"
|
19
20
|
>
|
20
21
|
<%== icon(:cpu) %>
|
21
|
-
Consumers
|
22
|
+
<span class="sidebar-nav-item-label">Consumers</span>
|
22
23
|
</a>
|
23
24
|
</li>
|
24
25
|
|
@@ -28,7 +29,7 @@
|
|
28
29
|
href="<%= root_path('jobs/running') %>"
|
29
30
|
>
|
30
31
|
<%== icon(:arrow_on_squares) %>
|
31
|
-
Jobs
|
32
|
+
<span class="sidebar-nav-item-label">Jobs</span>
|
32
33
|
</a>
|
33
34
|
</li>
|
34
35
|
|
@@ -38,7 +39,7 @@
|
|
38
39
|
href="<%= root_path('health/overview') %>"
|
39
40
|
>
|
40
41
|
<%== icon(:heart) %>
|
41
|
-
Health
|
42
|
+
<span class="sidebar-nav-item-label">Health</span>
|
42
43
|
</a>
|
43
44
|
</li>
|
44
45
|
|
@@ -48,7 +49,7 @@
|
|
48
49
|
href="<%= root_path('routing') %>"
|
49
50
|
>
|
50
51
|
<%== icon(:queue_list) %>
|
51
|
-
Routing
|
52
|
+
<span class="sidebar-nav-item-label">Routing</span>
|
52
53
|
</a>
|
53
54
|
</li>
|
54
55
|
|
@@ -58,7 +59,7 @@
|
|
58
59
|
href="<%= root_path('explorer') %>"
|
59
60
|
>
|
60
61
|
<%== icon(:document_glass) %>
|
61
|
-
Explorer
|
62
|
+
<span class="sidebar-nav-item-label">Explorer</span>
|
62
63
|
</a>
|
63
64
|
</li>
|
64
65
|
|
@@ -68,7 +69,7 @@
|
|
68
69
|
href="<%= root_path('recurring_tasks') %>"
|
69
70
|
>
|
70
71
|
<%== icon(:arrow_path_rounded) %>
|
71
|
-
Cron
|
72
|
+
<span class="sidebar-nav-item-label">Cron</span>
|
72
73
|
</a>
|
73
74
|
</li>
|
74
75
|
|
@@ -78,7 +79,7 @@
|
|
78
79
|
href="<%= root_path('scheduled_messages') %>"
|
79
80
|
>
|
80
81
|
<%== icon(:calendar) %>
|
81
|
-
Schedules
|
82
|
+
<span class="sidebar-nav-item-label">Schedules</span>
|
82
83
|
</a>
|
83
84
|
</li>
|
84
85
|
|
@@ -88,7 +89,7 @@
|
|
88
89
|
href="<%= root_path('errors') %>"
|
89
90
|
>
|
90
91
|
<%== icon(:bug) %>
|
91
|
-
Errors
|
92
|
+
<span class="sidebar-nav-item-label">Errors</span>
|
92
93
|
</a>
|
93
94
|
</li>
|
94
95
|
|
@@ -98,7 +99,7 @@
|
|
98
99
|
href="<%= root_path('dlq') %>"
|
99
100
|
>
|
100
101
|
<%== icon(:x_circle) %>
|
101
|
-
Dead
|
102
|
+
<span class="sidebar-nav-item-label">Dead</span>
|
102
103
|
</a>
|
103
104
|
</li>
|
104
105
|
|
@@ -108,7 +109,7 @@
|
|
108
109
|
href="<%= root_path('cluster') %>"
|
109
110
|
>
|
110
111
|
<%== icon(:blocks) %>
|
111
|
-
Cluster
|
112
|
+
<span class="sidebar-nav-item-label">Cluster</span>
|
112
113
|
</a>
|
113
114
|
</li>
|
114
115
|
|
@@ -118,7 +119,7 @@
|
|
118
119
|
href="<%= root_path('topics') %>"
|
119
120
|
>
|
120
121
|
<%== icon(:list_bullets) %>
|
121
|
-
Topics
|
122
|
+
<span class="sidebar-nav-item-label">Topics</span>
|
122
123
|
</a>
|
123
124
|
</li>
|
124
125
|
|
@@ -128,7 +129,7 @@
|
|
128
129
|
href="<%= root_path('status') %>"
|
129
130
|
>
|
130
131
|
<%== icon(:check_badge) %>
|
131
|
-
Status
|
132
|
+
<span class="sidebar-nav-item-label">Status</span>
|
132
133
|
</a>
|
133
134
|
</li>
|
134
135
|
|
@@ -138,8 +139,12 @@
|
|
138
139
|
href="<%= root_path('support') %>"
|
139
140
|
>
|
140
141
|
<%== icon(:lifebuoy) %>
|
141
|
-
Support
|
142
|
+
<span class="sidebar-nav-item-label">Support</span>
|
142
143
|
</a>
|
143
144
|
</li>
|
144
145
|
</ul>
|
146
|
+
|
147
|
+
<button type="button" class="btn-toggle-nav-collapsed grid gap-2 grid-flow-col items-center justify-start ml-6 text-sm invisible lg:visible" data-toggle-target="drawer-side">
|
148
|
+
<%== icon(:chevron) %>
|
149
|
+
</button>
|
145
150
|
</nav>
|
@@ -0,0 +1,20 @@
|
|
1
|
+
<% branding_cfg = Karafka::Web.config.ui.branding %>
|
2
|
+
<% if branding_cfg.label %>
|
3
|
+
<div class="branding-label text-left mt-4 ml-6">
|
4
|
+
<%==
|
5
|
+
public_send(
|
6
|
+
:"badge_#{branding_cfg.type}",
|
7
|
+
branding_cfg.label
|
8
|
+
)
|
9
|
+
%>
|
10
|
+
</div>
|
11
|
+
|
12
|
+
<div class="branding-mark text-left mt-4 ml-6">
|
13
|
+
<%==
|
14
|
+
public_send(
|
15
|
+
:"badge_#{branding_cfg.type}",
|
16
|
+
branding_cfg.label[0]
|
17
|
+
)
|
18
|
+
%>
|
19
|
+
</div>
|
20
|
+
<% end %>
|
@@ -0,0 +1,13 @@
|
|
1
|
+
<% branding_cfg = Karafka::Web.config.ui.branding %>
|
2
|
+
<% if branding_cfg.notice %>
|
3
|
+
<div id="branding" class="col-span-12">
|
4
|
+
<div class="mb-3">
|
5
|
+
<%==
|
6
|
+
public_send(
|
7
|
+
:"alert_#{branding_cfg.type}",
|
8
|
+
branding_cfg.notice
|
9
|
+
)
|
10
|
+
%>
|
11
|
+
</div>
|
12
|
+
</div>
|
13
|
+
<% end %>
|
@@ -18,17 +18,24 @@ module Karafka
|
|
18
18
|
#
|
19
19
|
# @param event [Karafka::Core::Monitoring::Event]
|
20
20
|
def on_error_occurred(event)
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
21
|
+
caller_ref = event[:caller]
|
22
|
+
|
23
|
+
# Collect extra info if it was a consumer related error.
|
24
|
+
# Those come from user code
|
25
|
+
details = case caller_ref
|
26
|
+
when Karafka::BaseConsumer
|
27
|
+
extract_consumer_info(caller_ref)
|
28
|
+
when Karafka::Connection::Client
|
29
|
+
extract_client_info(caller_ref)
|
30
|
+
when Karafka::Connection::Listener
|
31
|
+
extract_listener_info(caller_ref)
|
32
|
+
else
|
33
|
+
{}
|
34
|
+
end
|
29
35
|
|
30
|
-
|
36
|
+
error_class, error_message, backtrace = extract_error_info(event[:error])
|
31
37
|
|
38
|
+
track do |sampler|
|
32
39
|
sampler.errors << {
|
33
40
|
schema_version: SCHEMA_VERSION,
|
34
41
|
type: event[:type],
|
@@ -70,6 +77,7 @@ module Karafka
|
|
70
77
|
{
|
71
78
|
topic: consumer.topic.name,
|
72
79
|
consumer_group: consumer.topic.consumer_group.id,
|
80
|
+
subscription_group: consumer.topic.subscription_group.id,
|
73
81
|
partition: consumer.partition,
|
74
82
|
first_offset: consumer.messages.metadata.first_offset,
|
75
83
|
last_offset: consumer.messages.metadata.last_offset,
|
@@ -80,6 +88,27 @@ module Karafka
|
|
80
88
|
tags: consumer.tags
|
81
89
|
}
|
82
90
|
end
|
91
|
+
|
92
|
+
# @param client [::Karafka::Connection::Client]
|
93
|
+
# @return [Hash] hash with client specific info for details of error
|
94
|
+
def extract_client_info(client)
|
95
|
+
{
|
96
|
+
consumer_group: client.subscription_group.consumer_group.id,
|
97
|
+
subscription_group: client.subscription_group.id,
|
98
|
+
name: client.name,
|
99
|
+
id: client.id
|
100
|
+
}
|
101
|
+
end
|
102
|
+
|
103
|
+
# @param listener [::Karafka::Connection::Listener]
|
104
|
+
# @return [Hash] hash with listener specific info for details of error
|
105
|
+
def extract_listener_info(listener)
|
106
|
+
{
|
107
|
+
consumer_group: listener.subscription_group.consumer_group.id,
|
108
|
+
subscription_group: listener.subscription_group.id,
|
109
|
+
id: listener.id
|
110
|
+
}
|
111
|
+
end
|
83
112
|
end
|
84
113
|
end
|
85
114
|
end
|
@@ -10,13 +10,6 @@ module Karafka
|
|
10
10
|
# because there is no expectation on immediate status updates for producers and their
|
11
11
|
# dispatch flow is always periodic based.
|
12
12
|
class Reporter < Tracking::Reporter
|
13
|
-
# Minimum number of messages to produce to produce them in sync mode
|
14
|
-
# This acts as a small back-off not to overload the system in case we would have
|
15
|
-
# extremely big number of errors happening
|
16
|
-
PRODUCE_SYNC_THRESHOLD = 25
|
17
|
-
|
18
|
-
private_constant :PRODUCE_SYNC_THRESHOLD
|
19
|
-
|
20
13
|
# This mutex is shared between tracker and samplers so there is no case where metrics
|
21
14
|
# would be collected same time tracker reports
|
22
15
|
MUTEX = Mutex.new
|
@@ -82,7 +75,7 @@ module Karafka
|
|
82
75
|
# normal operations we should not have that many messages to dispatch and it should not
|
83
76
|
# slowdown any processing.
|
84
77
|
def produce(messages)
|
85
|
-
if messages.count >=
|
78
|
+
if messages.count >= ::Karafka::Web.config.tracking.producers.sync_threshold
|
86
79
|
::Karafka::Web.producer.produce_many_sync(messages)
|
87
80
|
else
|
88
81
|
::Karafka::Web.producer.produce_many_async(messages)
|
@@ -34,9 +34,10 @@ module Karafka
|
|
34
34
|
# @param name [String] button name
|
35
35
|
# @param path [String] path to where to go
|
36
36
|
# @param classes [String] extra css classes
|
37
|
+
# @param title [String, nil] title (if any)
|
37
38
|
# @return [String] button link html
|
38
|
-
def link_button(name, path, classes: '')
|
39
|
-
%(<a href="#{path}" class="btn #{classes}">#{name}</a>)
|
39
|
+
def link_button(name, path, classes: '', title: nil)
|
40
|
+
%(<a href="#{path}" class="btn #{classes}" title="#{title}">#{name}</a>)
|
40
41
|
end
|
41
42
|
|
42
43
|
# Defines various methods for badges and links that simplify defining them without
|
@@ -54,8 +55,8 @@ module Karafka
|
|
54
55
|
link_button(name, path, classes: "#{classes} btn-#{type}")
|
55
56
|
end
|
56
57
|
|
57
|
-
define_method :"link_button_#{type}_sm" do |name, path, classes: ''|
|
58
|
-
link_button(name, path, classes: "#{classes} btn-#{type} btn-sm")
|
58
|
+
define_method :"link_button_#{type}_sm" do |name, path, classes: '', title: nil|
|
59
|
+
link_button(name, path, classes: "#{classes} btn-#{type} btn-sm", title: title)
|
59
60
|
end
|
60
61
|
|
61
62
|
# @param message [String] alert message
|
@@ -51,7 +51,7 @@ function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"f
|
|
51
51
|
/*! Source: lib/karafka/web/ui/public/javascripts/charts/data_formatting_utility.js */
|
52
52
|
let DataFormattingUtils={niceBytes(e,t=2){let i=0,s=parseInt(e,10)||0;for(;1024<=s&&++i;)s/=1024;return s.toFixed(s<10&&0<i?1:t)+" "+["bytes","KB","MB","GB","TB","PB","EB","ZB","YB"][i]},formatLabelX(e,t){return"date"!==t?e:("00"+((t=new Date(1e3*e)).getMonth()+1)).slice(-2)+"/"+("00"+t.getDate()).slice(-2)+"/"+t.getFullYear()+" "+("00"+t.getHours()).slice(-2)+":"+("00"+t.getMinutes()).slice(-2)+":"+("00"+t.getSeconds()).slice(-2)},formatTooltip(e,t){var i=t.parsed.y,s=t.dataset.label;switch(e){case"percentage":return Math.floor(i)===i?s+": "+i+" %":s+": "+Math.round(100*i)/100+" %";case"memory":return s+": "+DataFormattingUtils.niceBytes(1024*i,2);default:return t.yLabel}},formatLabelY(e,t){switch(e){case"percentage":return Math.floor(t)===t?t+"%":Math.round(100*t)/100+"%";case"memory":return DataFormattingUtils.niceBytes(1024*t,1);default:return Math.floor(t)===t?t:Math.round(100*t)/100}},isFractionalPrecision(e){return e!==Math.floor(e)}};
|
53
53
|
/*! Source: lib/karafka/web/ui/public/javascripts/charts/dataset_state_manager.js */class DatasetStateManager{constructor(){this.storageKey="karafkaDisabledDatasets"}readAll(){var e=localStorage.getItem(this.storageKey);return e?JSON.parse(e):{}}saveAll(e){localStorage.setItem(this.storageKey,JSON.stringify(e))}saveCurrent(){var e=document.querySelectorAll(".chartjs"),t=window.location.href.split("?")[0];let i={};var s=this.readAll();e.forEach(e=>{var e=e.id,t=Chart.getChart(e);t&&t.legend&&t.legend.legendItems&&0<(t=t.legend.legendItems.map((e,t)=>e.hidden?t:null).filter(e=>null!==e)).length&&(i[e]=t)}),s[t]=i,this.saveAll(s)}getCurrentChart(e){var t=window.location.href.split("?")[0];return(this.readAll()[t]||{})[e]||[]}}
|
54
|
-
/*! Source: lib/karafka/web/ui/public/javascripts/components/btn_toggle_manager.js */class BtnToggleManager{constructor(){this.init()}init(){document.querySelectorAll(
|
54
|
+
/*! Source: lib/karafka/web/ui/public/javascripts/components/btn_toggle_manager.js */class BtnToggleManager{constructor(e=".btn-toggle",t="hidden"){this.btnClass=e,this.visibilityClass=t,this.init()}init(){document.querySelectorAll(this.btnClass).forEach(t=>{let i=t.getAttribute("data-toggle-target"),s=document.getElementById(i);s&&(this.restoreVisibility(t,s),t._isClickListenerAdded||(t.addEventListener("click",()=>{var e=!s.classList.contains(this.visibilityClass);s.classList.toggle(this.visibilityClass),t.classList.toggle("active",!e),this.saveVisibility(i,!e)}),t._isClickListenerAdded=!0))})}saveVisibility(e,t){localStorage.setItem(e+"_visibility",t)}restoreVisibility(e,t){var i=localStorage.getItem(t.id+"_visibility"),i=i?"true"===i:!t.classList.contains(this.visibilityClass);t.classList.toggle(this.visibilityClass,!i),e.classList.toggle("active",i)}}
|
55
55
|
/*! Source: lib/karafka/web/ui/public/javascripts/components/charts.js */function refreshCharts(e){(new LineChartsManager).refreshAndRender(e,!0),(new BarChartManager).refreshAndRenderBarCharts(e,!0)}function manageCharts(){(new LineChartsManager).refreshAndRender(document,!1),(new BarChartManager).refreshAndRenderBarCharts(document,!1)}
|
56
56
|
/*! Source: lib/karafka/web/ui/public/javascripts/components/live_poll.js */var livePollTimer=null,oldDOM=null,datePicker=null,startURL=window.location.href;let isHoveringOverClickable=!1;function initLivePolling(){document.addEventListener("mouseover",function(e){isElementClickable(e.target)&&(isHoveringOverClickable=!0)}),document.addEventListener("mouseout",function(e){isElementClickable(e.target)&&(isHoveringOverClickable=!1)}),null==localStorage.karafkaLivePoll&&(localStorage.karafkaLivePoll="enabled")}function isFormActive(){var e=document.activeElement;return["INPUT","TEXTAREA","SELECT","BUTTON","FIELDSET"].includes(e.tagName)}function isElementClickable(e){return!!("A"===e.tagName||"BUTTON"===e.tagName||"INPUT"===e.tagName&&("button"===e.type||"submit"===e.type)||e.hasAttribute("onclick")||"function"==typeof e.onclick||"SPAN"===e.tagName&&e.closest(".tab-container")||e.closest("button")||e.closest("a"))}function isUserHoveringOverClickable(){return isHoveringOverClickable}function isAnyTextSelected(){var e="";return void 0!==window.getSelection?e=window.getSelection().toString():void 0!==document.selection&&"Text"==document.selection.type&&(e=document.selection.createRange().text),""!=e}function isCollapsingHappening(){return 0<document.querySelectorAll(".collapsing").length}function isPollingPossible(e=!1){return!(isFormActive()||isUserHoveringOverClickable()||isAnyTextSelected()||isOffsetLookupCalendarVisible()||isAnyModalOpen()||isCollapsingHappening()||isTurboOperating()||e&&startURL!=window.location.href)}function isAnyModalOpen(){var e;for(e of document.querySelectorAll("dialog"))if(e.open)return!0;return!1}function bindPollingButtonClick(){var e=document.getElementById("live-poll");null!=e&&e.addEventListener("click",handleLivePollingButtonClick)}function handleLivePollingButtonClick(){toggleLivePollState(),setLivePollButton(),setPollingListener()}function toggleLivePollState(){"enabled"==localStorage.karafkaLivePoll?localStorage.karafkaLivePoll="disabled":localStorage.karafkaLivePoll="enabled"}function setLivePollButton(){null!=(selector=document.getElementById("live-poll"))&&("enabled"==localStorage.karafkaLivePoll?(selector.classList.add("text-base-content"),selector.classList.remove("text-gray-500")):(selector.classList.add("text-gray-500"),selector.classList.remove("text-base-content")))}function checkResponse(e){if(e.ok)return e;throw e}function refreshPage(e){if(!isPollingPossible())return!1;var t,e=(new DOMParser).parseFromString(e,"text/html"),i=e.getElementById("content");oldDOM!=i.innerHTML&&(t=document.querySelectorAll(".chartjs").length,0==i.querySelectorAll(".chartjs").length||0==t?(document.getElementById("content").replaceWith(i),addListeners()):(t=e.getElementById("refreshable"),document.getElementById("refreshable").replaceWith(t),refreshCharts(e)),oldDOM=i.innerHTML)}function showError(e){console.error(e)}function scheduleLivePoll(){null==oldDOM&&(oldDOM=document.getElementById("content").innerHTML);let e=parseInt(localStorage.karafkaTimeInterval)||5e3;e<1e3&&(localStorage.karafkaTimeInterval=5e3,e=5e3),livePollTimer=setTimeout(livePollCallback,e)}function livePollCallback(){clearTimeout(livePollTimer),livePollTimer=null,isPollingPossible(!1)?(startURL=window.location.href,fetch(window.location.href).then(checkResponse).then(e=>e.text()).then(refreshPage).catch(showError).finally(setPollingListener)):setPollingListener()}function setPollingListener(){var e=document.getElementById("live-poll"),t=localStorage.karafkaLivePoll;"disabled"==t||null==t||null==e?(clearTimeout(livePollTimer),livePollTimer=null):(clearTimeout(livePollTimer),scheduleLivePoll())}
|
57
57
|
/*! Source: lib/karafka/web/ui/public/javascripts/components/offset_datetime.js */function loadOffsetLookupDatePicker(){var e={locale:{days:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],daysShort:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],daysMin:["Su","Mo","Tu","We","Th","Fr","Sa"],months:["January","February","March","April","May","June","July","August","September","October","November","December"],monthsShort:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],today:"Today",clear:"Clear",dateFormat:"yyyy-MM-dd",timeFormat:"HH:mm",firstDay:1},timepicker:!0,onSelect:({})=>{document.getElementById("offset-lookup-datepicker").value=""},onShow:function(){offsetLookupDatePicker.selectDate((new Date).getTime()),offsetLookupDatePicker.maxDate=new Date},onHide:function(){offsetLookupDatePicker.selectDate((new Date).getTime())},buttons:[{content(e){return"Go to offset"},onClick(e){var t=e.selectedDates[0]||new Date,i=e.$el.dataset.target;e.hide(),location.href=i+"/"+formatRedirectDateTime(t)}}]};null!=offsetLookupDatePicker&&offsetLookupDatePicker.destroy(),null!=document.getElementById("offset-lookup-datepicker")&&((offsetLookupDatePicker=new AirDatepicker("#offset-lookup-datepicker",e)).maxDate=new Date,offsetLookupDatePicker.selectDate((new Date).getTime()))}function formatRedirectDateTime(e){return e.getFullYear()+`-${String(e.getMonth()+1).padStart(2,"0")}-${String(e.getDate()).padStart(2,"0")}/${String(e.getHours()).padStart(2,"0")}:`+String(e.getMinutes()).padStart(2,"0")}function isOffsetLookupCalendarVisible(){return null!=offsetLookupDatePicker&&offsetLookupDatePicker.visible}
|
@@ -59,6 +59,7 @@ let DataFormattingUtils={niceBytes(e,t=2){let i=0,s=parseInt(e,10)||0;for(;1024<
|
|
59
59
|
/*! Source: lib/karafka/web/ui/public/javascripts/components/tabs_manager.js */class TabsManager{constructor(){this.storageKey="karafkaActiveTabsv2"}readAllActiveTabs(){var e=localStorage.getItem(this.storageKey);return e?JSON.parse(e):{}}saveAllActiveTabs(e){localStorage.setItem(this.storageKey,JSON.stringify(e))}saveCurrentActiveTabs(){var e=document.querySelectorAll(".inline-tabs > .active"),t=window.location.href.split("?")[0];let i=[];var s=this.readAllActiveTabs();e.forEach(e=>{i.push(e.id)}),s[t]=i,this.saveAllActiveTabs(s)}setActiveTabs(){var e=window.location.href.split("?")[0],e=this.readAllActiveTabs()[e];(e=e||Array.from(document.querySelectorAll(".inline-tabs > .active")).map(e=>e.id))&&e.forEach(e=>{e=document.getElementById(e);e&&(e.parentElement.querySelectorAll(".custom-tab").forEach(function(e){e.classList.remove("active")}),e.classList.add("active"),document.getElementById(e.getAttribute("data-target")).classList.remove("hidden"))})}manageTabs(){this.setActiveTabs();var t=this;document.querySelectorAll(".inline-tabs > .custom-tab").forEach(function(e){e.addEventListener("click",function(e){this.parentElement.querySelectorAll(".custom-tab").forEach(function(e){e.classList.remove("active");e=e.getAttribute("data-target");document.getElementById(e).classList.add("hidden")}),this.classList.add("active"),t.saveCurrentActiveTabs(),t.setActiveTabs()})})}}
|
60
60
|
/*! Source: lib/karafka/web/ui/public/javascripts/components/theme_manager.js */class ThemeManager{constructor(){this.themeSelectorButton=document.getElementById("theme-selector"),this.themeSelectorLight=document.getElementById("theme-selector-light"),this.themeSelectorDark=document.getElementById("theme-selector-dark"),this.init()}init(){this.lightThemeLink=document.querySelector(".highlight-light"),this.darkThemeLink=document.querySelector(".highlight-dark"),this.lightThemeLink&&this.darkThemeLink&&this.themeSelectorButton?(this.restoreTheme(),this.bindThemeSelectorButton()):console.error("Theme CSS links or theme selector button not found")}bindThemeSelectorButton(){this.themeSelectorButton&&!this.themeSelectorButton.dataset.bound&&(this.themeSelectorButton.addEventListener("click",()=>{this.toggleTheme()}),this.themeSelectorButton.dataset.bound="true")}setTheme(e){document.documentElement.setAttribute("data-theme",e),"dark"===e?(this.lightThemeLink.disabled=!0,this.darkThemeLink.disabled=!1,this.themeSelectorLight.classList.add("hidden"),this.themeSelectorDark.classList.remove("hidden")):(this.lightThemeLink.disabled=!1,this.darkThemeLink.disabled=!0,this.themeSelectorLight.classList.remove("hidden"),this.themeSelectorDark.classList.add("hidden")),localStorage.setItem("theme",e)}toggleTheme(){var e=document.documentElement.getAttribute("data-theme");this.setTheme("dark"===e?"corporate":"dark")}restoreTheme(){var e=localStorage.getItem("theme"),e=e||(window.matchMedia("(prefers-color-scheme: dark)").matches?"dark":"corporate");this.setTheme(e),window.matchMedia("(prefers-color-scheme: dark)").addEventListener("change",e=>{localStorage.getItem("theme")||this.setTheme(e.matches?"dark":"corporate")})}}
|
61
61
|
/*! Source: lib/karafka/web/ui/public/javascripts/components/turbo_tracker.js */let turboIsOperating=!1;function isTurboOperating(){return turboIsOperating}
|
62
|
-
/*! Source: lib/karafka/web/ui/public/javascripts/application.js */function updateTimeAgo(){0!=(e=document.querySelectorAll("time")).length&&(timeago.render(e),timeago.cancel());for(var e=document.getElementsByClassName("time-title"),t=0;t<e.length;t++){var i=e[t],s=i.getAttribute("title");i.setAttribute("title",timeago.format(s))}}function refreshTitle(){var e=document.querySelectorAll(".breadcrumbs a"),e=Array.from(e).slice(1).map(e=>e.textContent.trim());0<e.length?document.title=e.join(" > ")+" - Karafka Web UI":document.title="Karafka Web UI"}function redirectToPartition(){var e=document.getElementById("current-partition");null!=e&&e.addEventListener("change",function(){Turbo.visit(this.value)})}function bindActionsConfirmations(){for(var t=document.getElementsByClassName("confirm-action"),i=0;i<t.length;i++){var s=t[i];let e="click";"FORM"===s.nodeName&&(e="submit"),s.addEventListener(e,function(e){window.confirm("Are you sure?")||e.preventDefault()})}}function bindLockableButtons(){document.querySelectorAll(".btn-lockable").forEach(function(i){i.addEventListener("click",function(e){var t=i.closest("form");t?t.addEventListener("submit",function(){i.disabled=!0,i.textContent+="...",document.querySelectorAll(".modal").forEach(function(e){e.classList.add("modal-locked")})},{once:!0}):(i.disabled=!0,i.textContent+="...")})})}function addListeners(){initLivePolling(),bindPollingButtonClick(),bindLockableButtons(),setLivePollButton(),setPollingListener(),hljs.highlightAll(),updateTimeAgo(),redirectToPartition(),(new TabsManager).manageTabs(),manageCharts(),bindActionsConfirmations(),loadOffsetLookupDatePicker(),new BtnToggleManager,new ThemeManager,refreshTitle(),new SearchMetadataVisibilityManager,new SearchModalManager}document.addEventListener("turbo:visit",function(){turboIsOperating=!0}),document.addEventListener("turbo:before-fetch-request",function(){turboIsOperating=!0}),document.addEventListener("turbo:before-fetch-response",function(){turboIsOperating=!0}),document.addEventListener("turbo:load",function(){turboIsOperating=!1}),document.addEventListener("turbo:frame-load",function(){turboIsOperating=!1}),document.addEventListener("turbo:frame-render",function(){turboIsOperating=!1}),document.addEventListener("turbo:load",addListeners),Turbo.setProgressBarDelay(100)
|
62
|
+
/*! Source: lib/karafka/web/ui/public/javascripts/application.js */function updateTimeAgo(){0!=(e=document.querySelectorAll("time")).length&&(timeago.render(e),timeago.cancel());for(var e=document.getElementsByClassName("time-title"),t=0;t<e.length;t++){var i=e[t],s=i.getAttribute("title");i.setAttribute("title",timeago.format(s))}}function refreshTitle(){var e=document.querySelectorAll(".breadcrumbs a"),e=Array.from(e).slice(1).map(e=>e.textContent.trim());0<e.length?document.title=e.join(" > ")+" - Karafka Web UI":document.title="Karafka Web UI"}function redirectToPartition(){var e=document.getElementById("current-partition");null!=e&&e.addEventListener("change",function(){Turbo.visit(this.value)})}function bindActionsConfirmations(){for(var t=document.getElementsByClassName("confirm-action"),i=0;i<t.length;i++){var s=t[i];let e="click";"FORM"===s.nodeName&&(e="submit"),s.addEventListener(e,function(e){window.confirm("Are you sure?")||e.preventDefault()})}}function bindLockableButtons(){document.querySelectorAll(".btn-lockable").forEach(function(i){i.addEventListener("click",function(e){var t=i.closest("form");t?t.addEventListener("submit",function(){i.disabled=!0,i.textContent+="...",document.querySelectorAll(".modal").forEach(function(e){e.classList.add("modal-locked")})},{once:!0}):(i.disabled=!0,i.textContent+="...")})})}function addListeners(){initLivePolling(),bindPollingButtonClick(),bindLockableButtons(),setLivePollButton(),setPollingListener(),hljs.highlightAll(),updateTimeAgo(),redirectToPartition(),(new TabsManager).manageTabs(),manageCharts(),bindActionsConfirmations(),loadOffsetLookupDatePicker(),new BtnToggleManager,new BtnToggleManager(".btn-toggle-nav-collapsed","collapsed"),new ThemeManager,refreshTitle(),new SearchMetadataVisibilityManager,new SearchModalManager}document.addEventListener("turbo:visit",function(){turboIsOperating=!0}),document.addEventListener("turbo:before-fetch-request",function(){turboIsOperating=!0}),document.addEventListener("turbo:before-fetch-response",function(){turboIsOperating=!0}),document.addEventListener("turbo:load",function(){turboIsOperating=!1}),document.addEventListener("turbo:frame-load",function(){turboIsOperating=!1}),document.addEventListener("turbo:frame-render",function(){turboIsOperating=!1}),document.addEventListener("turbo:load",addListeners),Turbo.setProgressBarDelay(100)
|
63
63
|
/*! Source: lib/karafka/web/ui/public/javascripts/charts/types/bar.js */;class BarChartManager{constructor(){this.datasetStateManager=new DatasetStateManager}refreshAndRenderBarCharts(c,u=!1){(u?c:document).querySelectorAll(".chartjs-bar").forEach(e=>{var t=e.id,i=(u?c:document).getElementById(t),s=JSON.parse(i.dataset.datasets);let r=[],a=[],n=[];var o=i.dataset.label_type_y;let l=i.dataset.label_type_x,h=this.datasetStateManager.getCurrentChart(t);Object.entries(s).forEach(([e,t],i)=>{t.forEach(([e,t])=>{n.push(t),0===i&&r.push(DataFormattingUtils.formatLabelX(e,l))}),a.push({data:t.map(([,e])=>e),label:e,hidden:h.includes(i),borderWidth:2.5})});var i=Math.min(...n),s=Math.max(...n),i=Math.round(i-.1*i),s=Math.round(s+.005*s),d=Math.round(n.reduce((e,t)=>e+t,0)/n.length);a.push({type:"line",label:"Average",data:new Array(r.length).fill(d),borderWidth:2,fill:!1,pointRadius:0,hoverBorderWidth:3,pointHitRadius:20}),u?((d=Chart.getChart(t)).data.datasets=a,d.data.labels=r,d.options.scales.y.min=i,d.options.scales.y.max=s,d.update("none")):this.renderBarChart(e,r,a,i,s,o)})}renderBarChart(e,t,i,s,r,a){new Chart(e,{type:"bar",data:{labels:t,datasets:i},options:{responsive:!0,maintainAspectRatio:!1,aspectRatio:5,scales:{x:{display:!0},y:{beginAtZero:!1,min:s,max:r,ticks:{maxTicksLimit:8,callback:function(e,t,i){return DataFormattingUtils.formatLabelY(a,e,t,i)}}}},animation:!1,animations:{colors:!1,x:!1},transitions:{active:{animation:{duration:!1}}},plugins:{legend:{position:"hidden"},tooltip:{callbacks:{label:function(e){let t=e.dataset.label||"";return"Average"!==t?DataFormattingUtils.formatTooltip(a,e):t+=": "+e.formattedValue}}}}}})}}
|
64
|
-
/*! Source: lib/karafka/web/ui/public/javascripts/charts/types/line.js */class LineChartsManager{constructor(){this.datasetStateManager=new DatasetStateManager}getLegendHeightPercentage(e){var t=e.chartArea,e=e.height,t=e-(t.bottom-t.top);return Math.round(t/e*100)}afterRenderPlugin(){let i=this;return{id:"afterRender",afterRender:function(e){var t=i.getLegendHeightPercentage(e),e=document.getElementById(e.canvas.id);50<t&&""==e.parentElement.style.height&&(e.parentElement.style.height="400px")}}}refreshAndRender(d,c=!1){(c?d:document).querySelectorAll(".chartjs-line").forEach(e=>{var t=e.id,i=(c?d:document).getElementById(t),s=JSON.parse(i.dataset.datasets);let r=[],a=[],n=0;var o=i.dataset.label_type_y;let l=i.dataset.label_type_x,h=this.datasetStateManager.getCurrentChart(t);Object.entries(s).forEach(([e,t],i)=>{t.forEach(([e,t])=>{0===i&&r.push(DataFormattingUtils.formatLabelX(e,l)),DataFormattingUtils.isFractionalPrecision(t)&&(n=2)}),a.push({data:t,label:e,hidden:h.includes(i),borderWidth:2.5,pointHitRadius:10})}),c?((i=Chart.getChart(t)).data.datasets=a,i.data.labels=r,i.update("none")):this.render(e,r,a,n,o)})}render(e,t,i,s,r){var a=null,a=10<i.length?"point":"x";new Chart(e,{type:"line",data:{labels:t,datasets:i},options:{responsive:!0,maintainAspectRatio:!1,aspectRatio:5,title:{display:!1},interaction:{mode:"nearest",axis:"x",intersect:!1},animation:!1,transitions:{active:{animation:{duration:!1}}},plugins:{legend:{position:"bottom",labels:{padding:20},onClick:(e,t,i)=>{var s=t.datasetIndex,i=i.chart;i.isDatasetVisible(s)?(i.hide(s),t.hidden=!0):(i.show(s),t.hidden=!1),this.datasetStateManager.saveCurrent()}},tooltip:{mode:a,filter:function(e,t,i){return t<10},callbacks:{label:function(e){return DataFormattingUtils.formatTooltip(r,e)}}}},scales:{x:{display:!1},y:{ticks:{precision:s,count:5,callback:function(e,t,i){return DataFormattingUtils.formatLabelY(r,e,t,i)}}}},elements:{point:{radius:0,style:!1},line:{style:"star",radius:0,spanGaps:!1}},hover:{mode:"index",intersect:!1}},plugins:[this.afterRenderPlugin()]})}}
|
64
|
+
/*! Source: lib/karafka/web/ui/public/javascripts/charts/types/line.js */class LineChartsManager{constructor(){this.datasetStateManager=new DatasetStateManager}getLegendHeightPercentage(e){var t=e.chartArea,e=e.height,t=e-(t.bottom-t.top);return Math.round(t/e*100)}afterRenderPlugin(){let i=this;return{id:"afterRender",afterRender:function(e){var t=i.getLegendHeightPercentage(e),e=document.getElementById(e.canvas.id);50<t&&""==e.parentElement.style.height&&(e.parentElement.style.height="400px")}}}refreshAndRender(d,c=!1){(c?d:document).querySelectorAll(".chartjs-line").forEach(e=>{var t=e.id,i=(c?d:document).getElementById(t),s=JSON.parse(i.dataset.datasets);let r=[],a=[],n=0;var o=i.dataset.label_type_y;let l=i.dataset.label_type_x,h=this.datasetStateManager.getCurrentChart(t);Object.entries(s).forEach(([e,t],i)=>{t.forEach(([e,t])=>{0===i&&r.push(DataFormattingUtils.formatLabelX(e,l)),DataFormattingUtils.isFractionalPrecision(t)&&(n=2)}),a.push({data:t,label:e,hidden:h.includes(i),borderWidth:2.5,pointHitRadius:10})}),c?((i=Chart.getChart(t)).data.datasets=a,i.data.labels=r,i.update("none")):this.render(e,r,a,n,o)})}render(e,t,i,s,r){var a=null,a=10<i.length?"point":"x";new Chart(e,{type:"line",data:{labels:t,datasets:i},options:{responsive:!0,maintainAspectRatio:!1,aspectRatio:5,title:{display:!1},interaction:{mode:"nearest",axis:"x",intersect:!1},animation:!1,transitions:{active:{animation:{duration:!1}}},plugins:{legend:{position:"bottom",labels:{padding:20},onClick:(e,t,i)=>{var s=t.datasetIndex,i=i.chart;i.isDatasetVisible(s)?(i.hide(s),t.hidden=!0):(i.show(s),t.hidden=!1),this.datasetStateManager.saveCurrent()}},tooltip:{mode:a,filter:function(e,t,i){return t<10},callbacks:{label:function(e){return DataFormattingUtils.formatTooltip(r,e)}}}},scales:{x:{display:!1},y:{ticks:{precision:s,count:5,callback:function(e,t,i){return DataFormattingUtils.formatLabelY(r,e,t,i)}}}},elements:{point:{radius:0,style:!1},line:{style:"star",radius:0,spanGaps:!1}},hover:{mode:"index",intersect:!1}},plugins:[this.afterRenderPlugin()]})}}
|
65
|
+
//# sourceMappingURL=application.min.js.map
|
Binary file
|
Binary file
|
@@ -1,10 +1,21 @@
|
|
1
|
+
/*
|
2
|
+
This class allows buttons to toggle visibility classes on target elements.
|
3
|
+
It also saves the visibility state in local storage so that it persists across page loads.
|
4
|
+
|
5
|
+
By default, it will look for elements with class 'btn-toggle' and toggle the
|
6
|
+
'hidden' class on their target elements (defined by the data attribute `data-toggle-target`)
|
7
|
+
when clicked.
|
8
|
+
*/
|
9
|
+
|
1
10
|
class BtnToggleManager {
|
2
|
-
constructor() {
|
11
|
+
constructor(btnClass = '.btn-toggle', visibilityClass = 'hidden') {
|
12
|
+
this.btnClass = btnClass;
|
13
|
+
this.visibilityClass = visibilityClass;
|
3
14
|
this.init();
|
4
15
|
}
|
5
16
|
|
6
17
|
init() {
|
7
|
-
document.querySelectorAll(
|
18
|
+
document.querySelectorAll(this.btnClass).forEach(button => {
|
8
19
|
const targetId = button.getAttribute('data-toggle-target');
|
9
20
|
const targetElement = document.getElementById(targetId);
|
10
21
|
|
@@ -13,13 +24,22 @@ class BtnToggleManager {
|
|
13
24
|
// Establish initial state from local storage or based on visibility
|
14
25
|
this.restoreVisibility(button, targetElement);
|
15
26
|
|
16
|
-
//
|
17
|
-
button.
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
27
|
+
// Check if the event listener has already been added
|
28
|
+
if (!button._isClickListenerAdded) {
|
29
|
+
// Define the event handler and store the flag to prevent duplicate listeners
|
30
|
+
const handleClick = () => {
|
31
|
+
const isVisible = !targetElement.classList.contains(this.visibilityClass);
|
32
|
+
targetElement.classList.toggle(this.visibilityClass);
|
33
|
+
button.classList.toggle('active', !isVisible);
|
34
|
+
this.saveVisibility(targetId, !isVisible);
|
35
|
+
};
|
36
|
+
|
37
|
+
// Add the event listener
|
38
|
+
button.addEventListener('click', handleClick);
|
39
|
+
|
40
|
+
// Set flag to indicate the listener has been added
|
41
|
+
button._isClickListenerAdded = true;
|
42
|
+
}
|
23
43
|
});
|
24
44
|
}
|
25
45
|
|
@@ -29,9 +49,9 @@ class BtnToggleManager {
|
|
29
49
|
|
30
50
|
restoreVisibility(button, targetElement) {
|
31
51
|
const storedVisibility = localStorage.getItem(targetElement.id + '_visibility');
|
32
|
-
const isVisible = storedVisibility ? (storedVisibility === 'true') : !targetElement.classList.contains(
|
52
|
+
const isVisible = storedVisibility ? (storedVisibility === 'true') : !targetElement.classList.contains(this.visibilityClass);
|
33
53
|
|
34
|
-
targetElement.classList.toggle(
|
54
|
+
targetElement.classList.toggle(this.visibilityClass, !isVisible);
|
35
55
|
button.classList.toggle('active', isVisible);
|
36
56
|
}
|
37
57
|
}
|
@@ -35,3 +35,24 @@ table td.commands {
|
|
35
35
|
table td.commands-inline-3 {
|
36
36
|
width: 180px
|
37
37
|
}
|
38
|
+
|
39
|
+
.drawer-side .btn-toggle-nav-collapsed svg {
|
40
|
+
transform: scale(1, 1);
|
41
|
+
transition: transform 0.2s;
|
42
|
+
}
|
43
|
+
|
44
|
+
.drawer-side.collapsed .btn-toggle-nav-collapsed svg {
|
45
|
+
transform: scale(-1, -1);
|
46
|
+
}
|
47
|
+
|
48
|
+
.drawer-side .btn-toggle-nav-collapsed::after {
|
49
|
+
content: 'Collapse';
|
50
|
+
}
|
51
|
+
|
52
|
+
.drawer-side.collapsed .btn-toggle-nav-collapsed::after {
|
53
|
+
content: none;
|
54
|
+
}
|
55
|
+
|
56
|
+
.drawer-side.collapsed:hover .btn-toggle-nav-collapsed::after {
|
57
|
+
content: 'Expand';
|
58
|
+
}
|