karafka-web 0.10.1 → 0.10.2

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 (46) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +3 -1
  3. data/.ruby-version +1 -1
  4. data/CHANGELOG.md +8 -1
  5. data/Gemfile.lock +3 -3
  6. data/karafka-web.gemspec +1 -1
  7. data/lib/karafka/web/pro/ui/app.rb +35 -0
  8. data/lib/karafka/web/pro/ui/controllers/scheduled_messages/base_controller.rb +29 -0
  9. data/lib/karafka/web/pro/ui/controllers/scheduled_messages/explorer_controller.rb +65 -0
  10. data/lib/karafka/web/pro/ui/controllers/scheduled_messages/schedules_controller.rb +84 -0
  11. data/lib/karafka/web/pro/ui/views/explorer/_partition_option.erb +10 -2
  12. data/lib/karafka/web/pro/ui/views/recurring_tasks/_not_active.erb +1 -1
  13. data/lib/karafka/web/pro/ui/views/scheduled_messages/explorer/_breadcrumbs.erb +30 -0
  14. data/lib/karafka/web/pro/ui/views/scheduled_messages/explorer/_message.erb +84 -0
  15. data/lib/karafka/web/pro/ui/views/scheduled_messages/explorer/_messages.erb +28 -0
  16. data/lib/karafka/web/pro/ui/views/scheduled_messages/explorer/partition.erb +72 -0
  17. data/lib/karafka/web/pro/ui/views/scheduled_messages/explorer/topic.erb +33 -0
  18. data/lib/karafka/web/pro/ui/views/scheduled_messages/schedules/_breadcrumbs.erb +21 -0
  19. data/lib/karafka/web/pro/ui/views/scheduled_messages/schedules/_no_groups.erb +11 -0
  20. data/lib/karafka/web/pro/ui/views/scheduled_messages/schedules/index.erb +38 -0
  21. data/lib/karafka/web/pro/ui/views/scheduled_messages/schedules/show.erb +48 -0
  22. data/lib/karafka/web/pro/ui/views/search/_breadcrumbs.erb +1 -0
  23. data/lib/karafka/web/pro/ui/views/shared/_navigation.erb +10 -0
  24. data/lib/karafka/web/tracking/consumers/listeners/errors.rb +3 -1
  25. data/lib/karafka/web/ui/base.rb +1 -1
  26. data/lib/karafka/web/ui/controllers/base_controller.rb +18 -3
  27. data/lib/karafka/web/ui/helpers/application_helper.rb +21 -7
  28. data/lib/karafka/web/ui/helpers/paths_helper.rb +18 -0
  29. data/lib/karafka/web/ui/models/recurring_tasks/log.rb +0 -11
  30. data/lib/karafka/web/ui/models/recurring_tasks/schedule.rb +0 -11
  31. data/lib/karafka/web/ui/models/recurring_tasks/task.rb +0 -11
  32. data/lib/karafka/web/ui/public/javascripts/application.min.js +1 -1
  33. data/lib/karafka/web/ui/public/javascripts/application.min.js.br +0 -0
  34. data/lib/karafka/web/ui/public/javascripts/application.min.js.gz +0 -0
  35. data/lib/karafka/web/ui/public/javascripts/components/live_poll.js +15 -0
  36. data/lib/karafka/web/ui/public/stylesheets/application.min.css +1 -1
  37. data/lib/karafka/web/ui/public/stylesheets/application.min.css.br +0 -0
  38. data/lib/karafka/web/ui/public/stylesheets/application.min.css.gz +0 -0
  39. data/lib/karafka/web/ui/public/stylesheets/libs/tailwind.css +1 -1
  40. data/lib/karafka/web/ui/views/shared/_breadcrumbs.erb +1 -1
  41. data/lib/karafka/web/ui/views/shared/_navigation.erb +10 -0
  42. data/lib/karafka/web/ui/views/shared/icons/_calendar.erb +3 -0
  43. data/lib/karafka/web/version.rb +1 -1
  44. data.tar.gz.sig +0 -0
  45. metadata +19 -5
  46. metadata.gz.sig +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 40794ee9c8b084cf75de0403b904134cbc6a762dbfa338bb9ce574b56e46ac36
4
- data.tar.gz: dedefe087c54e118abb90e819b36b29aa253c4351aa18bd8a78d01e2c096ce79
3
+ metadata.gz: d471de1bcc756c234f8db2345c269b878863759fb5deb195ac8579e57365efde
4
+ data.tar.gz: 12d1348a0b83353dabeeea7a5ae164be7ff834d84088cfadb7b32c7343470f66
5
5
  SHA512:
6
- metadata.gz: 88b9b6ed8082b0484dcd32a20b2cee2b77d4df762b65d0487325e03ef375e1e7ac621d612f81b3f4a6870aa4352e07286979863d656161ca7d8d880e5709d108
7
- data.tar.gz: f9350f68d872c76d289933fbf2548b692179bae30fb2c0fccf923cdefca7131bbf3e6bf362e21a442c424fc4b43472e8334115b90c32449e80ef45a3518c3228
6
+ metadata.gz: 3f3eab846d445aa01714c8cea282874f9228f69af2475408d19a34b3ce43793b235f32c4484b640fad3b36ae29c90a2a8112dfd0b46685159528672355945f4c
7
+ data.tar.gz: f44a24702afe474270232a1cd5d785737fbd3e6d3b3e574b3eeb1cba5680147000092ec564ad5da7c663d6de124c7b59d9c3bd6c4e51ec80fc249eb90627fb5c
checksums.yaml.gz.sig CHANGED
@@ -1 +1,3 @@
1
- ��[����St���Y�Ě�D��������1�#�]; Xły}�)ҙ�*��A ��uѭȚܟ��
1
+ @��)oEe۫�15��Ƣ�h�){
2
+ R�
3
+ �O�ljJ�F�B�F�R+u��G���������ev����y ~�D�����>�%�LikH��K���}S�[�>k�uM����
data/.ruby-version CHANGED
@@ -1 +1 @@
1
- 3.3.4
1
+ 3.3.5
data/CHANGELOG.md CHANGED
@@ -1,6 +1,13 @@
1
1
  # Karafka Web Changelog
2
2
 
3
- ## 0.10.1 (Unreleased)
3
+ ## 0.10.2 (2024-09-03)
4
+ - **[Feature]** Support Future Messages management (Pro).
5
+ - [Enhancement] Do not live-reload when form active.
6
+ - [Fix] Undefined method `deep_merge` for an instance of Hash.
7
+ - [Fix] Prevent live-polling on elements wrapped in a button.
8
+ - [Fix] Fix errors extractor failure on first message-less tick / eofed
9
+
10
+ ## 0.10.1 (2024-08-23)
4
11
  - **[Feature]** Support Recurring Tasks management (Pro).
5
12
  - [Enhancement] Optimize command buttons so they occupy less space.
6
13
  - [Enhancement] Improve tables headers capitalization.
data/Gemfile.lock CHANGED
@@ -1,9 +1,9 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- karafka-web (0.10.1)
4
+ karafka-web (0.10.2)
5
5
  erubi (~> 1.4)
6
- karafka (>= 2.4.9, < 2.5.0)
6
+ karafka (>= 2.4.10, < 2.5.0)
7
7
  karafka-core (>= 2.4.0, < 2.5.0)
8
8
  roda (~> 3.68, >= 3.69)
9
9
  tilt (~> 2.0)
@@ -40,7 +40,7 @@ GEM
40
40
  raabro (~> 1.4)
41
41
  i18n (1.14.5)
42
42
  concurrent-ruby (~> 1.0)
43
- karafka (2.4.9)
43
+ karafka (2.4.10)
44
44
  base64 (~> 0.2)
45
45
  karafka-core (>= 2.4.3, < 2.5.0)
46
46
  karafka-rdkafka (>= 0.17.2)
data/karafka-web.gemspec CHANGED
@@ -17,7 +17,7 @@ Gem::Specification.new do |spec|
17
17
  spec.licenses = %w[LGPL-3.0-only Commercial]
18
18
 
19
19
  spec.add_dependency 'erubi', '~> 1.4'
20
- spec.add_dependency 'karafka', '>= 2.4.9', '< 2.5.0'
20
+ spec.add_dependency 'karafka', '>= 2.4.10', '< 2.5.0'
21
21
  spec.add_dependency 'karafka-core', '>= 2.4.0', '< 2.5.0'
22
22
  spec.add_dependency 'roda', '~> 3.68', '>= 3.69'
23
23
  spec.add_dependency 'tilt', '~> 2.0'
@@ -272,6 +272,41 @@ module Karafka
272
272
  end
273
273
  end
274
274
 
275
+ r.on 'scheduled_messages' do
276
+ r.on 'schedules' do
277
+ controller = Controllers::ScheduledMessages::SchedulesController.new(params)
278
+
279
+ r.get String do |topic_id|
280
+ controller.show(topic_id)
281
+ end
282
+
283
+ r.get do
284
+ controller.index
285
+ end
286
+ end
287
+
288
+ r.on 'explorer' do
289
+ controller = Controllers::ScheduledMessages::ExplorerController.new(params)
290
+
291
+ r.get String do |topic_id|
292
+ controller.topic(topic_id)
293
+ end
294
+
295
+ r.get String, Integer do |topic_id, partition_id|
296
+ controller.partition(topic_id, partition_id)
297
+ end
298
+
299
+ # Jumps to offset matching the expected time
300
+ r.get String, Integer, Time do |topic_id, partition_id, time|
301
+ controller.closest(topic_id, partition_id, time)
302
+ end
303
+ end
304
+
305
+ r.get do
306
+ r.redirect root_path('scheduled_messages/schedules')
307
+ end
308
+ end
309
+
275
310
  r.on 'health' do
276
311
  controller = Controllers::HealthController.new(params)
277
312
 
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ # This Karafka component is a Pro component under a commercial license.
4
+ # This Karafka component is NOT licensed under LGPL.
5
+ #
6
+ # All of the commercial components are present in the lib/karafka/pro directory of this
7
+ # repository and their usage requires commercial license agreement.
8
+ #
9
+ # Karafka has also commercial-friendly license, commercial support and commercial components.
10
+ #
11
+ # By sending a pull request to the pro components, you are agreeing to transfer the copyright of
12
+ # your code to Maciej Mensfeld.
13
+
14
+ module Karafka
15
+ module Web
16
+ module Pro
17
+ module Ui
18
+ module Controllers
19
+ # Namespace for all controllers related to scheduled messages
20
+ module ScheduledMessages
21
+ # Base Pro controller for scheduled messages
22
+ class BaseController < Controllers::BaseController
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,65 @@
1
+ # frozen_string_literal: true
2
+
3
+ # This Karafka component is a Pro component under a commercial license.
4
+ # This Karafka component is NOT licensed under LGPL.
5
+ #
6
+ # All of the commercial components are present in the lib/karafka/pro directory of this
7
+ # repository and their usage requires commercial license agreement.
8
+ #
9
+ # Karafka has also commercial-friendly license, commercial support and commercial components.
10
+ #
11
+ # By sending a pull request to the pro components, you are agreeing to transfer the copyright of
12
+ # your code to Maciej Mensfeld.
13
+
14
+ module Karafka
15
+ module Web
16
+ module Pro
17
+ module Ui
18
+ module Controllers
19
+ module ScheduledMessages
20
+ # Allows for exploration of dispatch messages in a less generic form that via the
21
+ # explorer as different details are present
22
+ class ExplorerController < BaseController
23
+ # Displays aggregated messages from (potentially) all partitions of a topic
24
+ #
25
+ # @param topic_id [String]
26
+ def topic(topic_id)
27
+ response = Controllers::ExplorerController
28
+ .new(@params)
29
+ .topic(topic_id)
30
+
31
+ render(attributes: response.attributes)
32
+ end
33
+
34
+ # Shows messages available in a given partition
35
+ #
36
+ # @param topic_id [String]
37
+ # @param partition_id [Integer]
38
+ def partition(topic_id, partition_id)
39
+ response = Controllers::ExplorerController
40
+ .new(@params)
41
+ .partition(topic_id, partition_id)
42
+
43
+ render(attributes: response.attributes)
44
+ end
45
+
46
+ # Finds the closest offset matching the requested time and redirects to this location
47
+ # Note, that it redirects to closest but always younger.
48
+ #
49
+ # @param topic_id [String]
50
+ # @param partition_id [Integer]
51
+ # @param time [Time] time of the message
52
+ def closest(topic_id, partition_id, time)
53
+ response = Controllers::ExplorerController
54
+ .new(@params)
55
+ .closest(topic_id, partition_id, time)
56
+
57
+ redirect("scheduled_messages/#{response.path}")
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,84 @@
1
+ # frozen_string_literal: true
2
+
3
+ # This Karafka component is a Pro component under a commercial license.
4
+ # This Karafka component is NOT licensed under LGPL.
5
+ #
6
+ # All of the commercial components are present in the lib/karafka/pro directory of this
7
+ # repository and their usage requires commercial license agreement.
8
+ #
9
+ # Karafka has also commercial-friendly license, commercial support and commercial components.
10
+ #
11
+ # By sending a pull request to the pro components, you are agreeing to transfer the copyright of
12
+ # your code to Maciej Mensfeld.
13
+
14
+ module Karafka
15
+ module Web
16
+ module Pro
17
+ module Ui
18
+ module Controllers
19
+ # Namespace for all controllers related to scheduled messages
20
+ module ScheduledMessages
21
+ # Controller to display list of schedules (groups) and details about each
22
+ class SchedulesController < BaseController
23
+ # Displays list of groups
24
+ def index
25
+ topics = Models::Topic.all
26
+
27
+ # Names of scheduled messages topics defined in the routing
28
+ # They may not exist (yet) so we filter them based on the existing topics in the
29
+ # cluster
30
+ candidates = Karafka::App
31
+ .routes
32
+ .map(&:topics)
33
+ .map(&:to_a)
34
+ .flatten
35
+ .select(&:scheduled_messages?)
36
+ .reject { |topic| topic.name.end_with?(states_postfix) }
37
+ .map(&:name)
38
+ .sort
39
+
40
+ @topics = topics.select { |topic| candidates.include?(topic.topic_name) }
41
+
42
+ render
43
+ end
44
+
45
+ # Displays all partitions statistics (if any) with number of messages to dispatch
46
+ # @param schedule_name [String] name of the schedules messages topic
47
+ def show(schedule_name)
48
+ @schedule_name = schedule_name
49
+ @stats_topic_name = "#{schedule_name}#{states_postfix}"
50
+ @stats_info = Karafka::Admin.topic_info(@stats_topic_name)
51
+
52
+ @states = {}
53
+ @stats_info[:partition_count].times { |i| @states[i] = false }
54
+
55
+ Karafka::Pro::Iterator.new({ @stats_topic_name => -1 }).each do |message|
56
+ @states[message.partition] = message.payload
57
+ end
58
+
59
+ # Sort by partition id
60
+ @states = @states.sort_by { |key, _| key.to_s }.to_h
61
+ # Sort daily from closest date
62
+ @states.each_value do |details|
63
+ # Skip false predefined values from sorting
64
+ next unless details
65
+
66
+ details[:daily] = details[:daily].sort_by { |key, _| key.to_s }.to_h
67
+ end
68
+
69
+ render
70
+ end
71
+
72
+ private
73
+
74
+ # @return [String] states topic postfix
75
+ def states_postfix
76
+ @states_postfix ||= Karafka::App.config.scheduled_messages.states_postfix
77
+ end
78
+ end
79
+ end
80
+ end
81
+ end
82
+ end
83
+ end
84
+ end
@@ -1,7 +1,15 @@
1
+ <%
2
+ path = if @selector_path_method
3
+ public_send(@selector_path_method, @topic_id, partition)
4
+ else
5
+ explorer_path(@topic_id, partition)
6
+ end
7
+ %>
8
+
1
9
  <% if @partition_id == partition %>
2
- <option value="<%= explorer_path(@topic_id, partition) %>" selected=selected>
10
+ <option value="<%= path %>" selected=selected>
3
11
  <% else %>
4
- <option value="<%= explorer_path(@topic_id, partition) %>">
12
+ <option value="<%= path %>">
5
13
  <% end %>
6
14
  <%= partition || 'All' %>
7
15
  </option>
@@ -7,6 +7,6 @@
7
7
  <li>Recurring Tasks are enabled in your routing configuration.</li>
8
8
  <li>The necessary Kafka topics have been created.</li>
9
9
  <li>A schedule has been defined.</li>
10
- <li>our Karafka server, with schedule awareness, is running and has persisted the state.</li>
10
+ <li>Your Karafka server, with schedule awareness, is running and has persisted the state.</li>
11
11
  </ul>
12
12
  <% end %>
@@ -0,0 +1,30 @@
1
+ <li>
2
+ <a href="<%= root_path('scheduled_messages') %>">
3
+ Scheduled Messages
4
+ </a>
5
+ </li>
6
+
7
+ <% if current_path.include?('/explorer') %>
8
+ <li>
9
+ <a href="<%= root_path("scheduled_messages/explorer/#{@topic_id}") %>">
10
+ Messages
11
+ </a>
12
+ </li>
13
+ <% end %>
14
+
15
+ <% if @topic_id %>
16
+ <li>
17
+ <a href="<%= root_path("scheduled_messages/explorer/#{@topic_id}") %>">
18
+ <%= @topic_id %>
19
+ </a>
20
+ </li>
21
+ <% end %>
22
+
23
+ <% if @partition_id %>
24
+ <li>
25
+ <a href="<%= root_path("scheduled_messages/explorer/#{@topic_id}/#{@partition_id}") %>">
26
+ Partition
27
+ <%= @partition_id %>
28
+ </a>
29
+ </li>
30
+ <% end %>
@@ -0,0 +1,84 @@
1
+ <% safe_key = ::Karafka::Web::Pro::Ui::Lib::SafeRunner.new { message.key } %>
2
+
3
+ <% if message.is_a?(Array) %>
4
+ <tr>
5
+ <td class="text-muted">
6
+ <%= message[0] %>
7
+ </td>
8
+ <td class="text-muted">
9
+ <%= message[1] %>
10
+ </td>
11
+ <td colspan="8" class="text-center text-muted">
12
+ This offset does not contain any data. The message may have been compacted or is a system entry.
13
+ </td>
14
+ </tr>
15
+ <% else %>
16
+ <% type = message.headers['schedule_source_type'] %>
17
+ <tr>
18
+ <td>
19
+ <%= message.partition %>
20
+ </td>
21
+ <td>
22
+ <%= message.offset %>
23
+ </td>
24
+ <td>
25
+ <% if type == 'tombstone' %>
26
+ <%== badge_secondary type %>
27
+ <% end %>
28
+
29
+ <% if type == 'cancel' %>
30
+ <%== badge_warning type %>
31
+ <% end %>
32
+
33
+ <% if type == 'schedule' %>
34
+ <%== badge_primary type %>
35
+ <% end %>
36
+ </td>
37
+ <td>
38
+ <%= message.headers['schedule_schema_version'] %>
39
+ </td>
40
+
41
+ <% if type == 'cancel' %>
42
+ <td colspan="5" class="text-center text-muted">
43
+ Cancellation messages do not contain those details.
44
+ </td>
45
+ <% else %>
46
+ <td>
47
+ <%== relative_time(message.timestamp) %>
48
+ </td>
49
+ <td>
50
+ <%== relative_time message.headers['schedule_target_epoch'].to_i %>
51
+ </td>
52
+ <td>
53
+ <% if @visibility_filter.key?(message) %>
54
+ <% if safe_key.success? %>
55
+ <%= safe_key.result %>
56
+ <% else %>
57
+ <span class="text-muted">[Deserialization Failed]</span>
58
+ <% end %>
59
+ <% else %>
60
+ <span class="text-muted">[Filtered]</span>
61
+ <% end %>
62
+ </td>
63
+ <td>
64
+ <%= message.headers['schedule_target_topic'] %>
65
+ </td>
66
+ <td>
67
+ <% if @visibility_filter.key?(message) %>
68
+ <%= message.headers['schedule_target_key'] %>
69
+ <% else %>
70
+ <span class="text-muted">[Filtered]</span>
71
+ <% end %>
72
+ </td>
73
+ <% end %>
74
+
75
+ <td>
76
+ <%==
77
+ link_button_primary_sm(
78
+ 'Details',
79
+ explorer_path(message.topic, message.partition, message.offset)
80
+ )
81
+ %>
82
+ </td>
83
+ </tr>
84
+ <% end %>
@@ -0,0 +1,28 @@
1
+ <div class="data-table-wrapper">
2
+ <table class="data-table">
3
+ <thead>
4
+ <tr>
5
+ <th>Partition</th>
6
+ <th>Offset</th>
7
+ <th>Type</th>
8
+ <th>Schema</th>
9
+ <th>Created At</th>
10
+ <th>Dispatch At</th>
11
+ <th>Key</th>
12
+ <th>Target Topic</th>
13
+ <th>Target Key</th>
14
+ <th></th>
15
+ </tr>
16
+ </thead>
17
+ <tbody>
18
+ <%==
19
+ each_partial(
20
+ @messages,
21
+ 'scheduled_messages/explorer/message'
22
+ )
23
+ %>
24
+ </tbody>
25
+ </table>
26
+
27
+ <%== content_for :table_metadata %>
28
+ </div>
@@ -0,0 +1,72 @@
1
+ <% view_title "#{@topic_id} partition #{@partition_id}" %>
2
+
3
+ <% @selector_path_method = :scheduled_messages_explorer_path %>
4
+
5
+ <div class="col-span-4">
6
+ <section class="actions">
7
+ <% if @messages && !@messages.empty? %>
8
+ <a
9
+ href="<%= explorer_path(@topic_id, @partition_id, 'recent') %>"
10
+ class="btn-action"
11
+ title="Display the most recent message for this partition with auto-refresh"
12
+ >
13
+ <%== icon(:play_circle) %>
14
+ </a>
15
+
16
+ <a
17
+ href="<%= explorer_path(@topic_id, 'search', "?partition=#{@partition_id}") %>"
18
+ class="btn-action"
19
+ title="Search in this topic"
20
+ >
21
+ <%== icon(:magnifying_glass) %>
22
+ </a>
23
+
24
+ <% closest_path = scheduled_messages_explorer_path(@topic_id, @partition_id) %>
25
+ <input
26
+ type="image"
27
+ src="<%= asset_path('images/calendar.svg') %>"
28
+ width="45"
29
+ height="32"
30
+ class="btn-action p-1 opacity-60"
31
+ id="offset-lookup-datepicker"
32
+ value=""
33
+ data-target="<%= closest_path %>"
34
+ />
35
+ <% end %>
36
+ </section>
37
+ </div>
38
+
39
+ <div class="col-span-8 mb-3">
40
+ <section class="actions">
41
+ <%== partial 'explorer/selector' %>
42
+ </section>
43
+ </div>
44
+
45
+ <div class="col-span-12">
46
+ <% if @limited %>
47
+ <%== partial('explorer/topic/limited') %>
48
+ <% end %>
49
+
50
+ <% if @watermark_offsets.empty? && params.current_page == 1 %>
51
+ <%== partial 'explorer/partition/empty' %>
52
+ <% elsif @watermark_offsets.cleaned? && params.current_page == 1 %>
53
+ <%== partial 'explorer/partition/cleaned' %>
54
+ <% elsif @messages.empty? %>
55
+ <%== partial 'shared/no_paginated_data' %>
56
+ <% else %>
57
+ <% content_for :table_metadata do %>
58
+ <p class="table_metadata">
59
+ Watermark offsets:
60
+ <span class="badge badge-secondary mt-1 mb-1">
61
+ high: <%= @watermark_offsets.high %>
62
+ </span>
63
+
64
+ <span class="badge badge-secondary mt-1 mb-1">
65
+ low: <%= @watermark_offsets.low %>
66
+ </span>
67
+ </p>
68
+ <% end %>
69
+
70
+ <%== partial('scheduled_messages/explorer/messages') %>
71
+ <% end %>
72
+ </div>
@@ -0,0 +1,33 @@
1
+ <% view_title @topic_id %>
2
+
3
+ <% @selector_path_method = :scheduled_messages_explorer_path %>
4
+
5
+ <%== partial 'explorer/topic/actions' %>
6
+
7
+ <div class="col-span-12">
8
+ <% if @limited %>
9
+ <div class="mb-6">
10
+ <%== partial('explorer/topic/limited') %>
11
+ </div>
12
+ <% end %>
13
+
14
+ <% if @messages.empty? && params.current_page == 1 %>
15
+ <%== partial 'explorer/topic/empty' %>
16
+ <% elsif @messages.empty? %>
17
+ <%== partial 'shared/no_paginated_data' %>
18
+ <% else %>
19
+ <% content_for :table_metadata do %>
20
+ <p class="table_metadata">
21
+ Partitions:
22
+
23
+ <%== badge("total: #{@partitions_count}") %>
24
+ <%==
25
+ range = [@active_partitions.first, @active_partitions.last].uniq.join(' to ')
26
+ badge("visible: #{range}")
27
+ %>
28
+ </p>
29
+ <% end %>
30
+
31
+ <%== partial('scheduled_messages/explorer/messages') %>
32
+ <% end %>
33
+ </div>
@@ -0,0 +1,21 @@
1
+ <li>
2
+ <a href="<%= root_path('scheduled_messages') %>">
3
+ Scheduled Messages
4
+ </a>
5
+ </li>
6
+
7
+ <% if current_path.include?('/schedules') %>
8
+ <li>
9
+ <a href="<%= root_path('scheduled_messages/schedules') %>">
10
+ Schedules
11
+ </a>
12
+ </li>
13
+ <% end %>
14
+
15
+ <% if @schedule_name %>
16
+ <li>
17
+ <a href="<%= root_path("scheduled_messages/schedules/#{@schedule_name}") %>">
18
+ <%= @schedule_name %>
19
+ </a>
20
+ </li>
21
+ <% end %>
@@ -0,0 +1,11 @@
1
+ <% alert_box_info 'Scheduled Messages Data Not Available' do %>
2
+ <p class="mb-2">
3
+ We are unable to display data related to scheduled messages. Please ensure that:
4
+ </p>
5
+
6
+ <ul class="list-disc list-inside">
7
+ <li>Scheduled Messages are enabled in your routing configuration.</li>
8
+ <li>The necessary Kafka topics have been created.</li>
9
+ <li>Your Karafka server, with scheduled messages awareness, is running and has persisted the state.</li>
10
+ </ul>
11
+ <% end %>
@@ -0,0 +1,38 @@
1
+ <% view_title 'Schedules' %>
2
+
3
+ <div class="col-span-12">
4
+ <% if @topics.empty? %>
5
+ <%== partial 'scheduled_messages/schedules/no_groups' %>
6
+ <% else %>
7
+ <% @topics.each do |topic| %>
8
+ <div class="grid grid-cols-1 md:grid-cols-2 gap-8">
9
+ <div class="card-support">
10
+ <h3>
11
+ <%== icon(:calendar) %>
12
+ <span>
13
+ <%= topic.topic_name %>
14
+ /
15
+ <%= topic.partition_count %>
16
+ </span>
17
+ </h3>
18
+
19
+ <p class="flex justify-center space-x-2 mb-3">
20
+ <a
21
+ href="<%= root_path("scheduled_messages/schedules/#{topic.topic_name}") %>"
22
+ class="btn btn-primary btn-sm flex-1"
23
+ >
24
+ Planned
25
+ </a>
26
+
27
+ <a
28
+ href="<%= root_path("scheduled_messages/explorer/#{topic.topic_name}") %>"
29
+ class="btn btn-primary btn-sm flex-1"
30
+ >
31
+ Messages
32
+ </a>
33
+ </p>
34
+ </div>
35
+ </div>
36
+ <% end %>
37
+ <% end %>
38
+ </div>