karafka-web 0.9.1 → 0.10.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (417) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/.github/workflows/ci.yml +30 -0
  4. data/.gitignore +2 -0
  5. data/.ruby-version +1 -1
  6. data/CHANGELOG.md +85 -1
  7. data/Gemfile +1 -0
  8. data/Gemfile.lock +30 -25
  9. data/LICENSE +1 -1
  10. data/bin/build_assets +51 -0
  11. data/bin/release +6 -0
  12. data/config/locales/pro_errors.yml +18 -0
  13. data/docker-compose.yml +1 -1
  14. data/gulpfile.js +73 -0
  15. data/karafka-web.gemspec +2 -2
  16. data/lib/karafka/web/config.rb +9 -10
  17. data/lib/karafka/web/contracts/base.rb +2 -0
  18. data/lib/karafka/web/contracts/config.rb +2 -1
  19. data/lib/karafka/web/errors.rb +12 -0
  20. data/lib/karafka/web/inflector.rb +1 -1
  21. data/lib/karafka/web/management/actions/enable.rb +11 -0
  22. data/lib/karafka/web/management/migrations/consumers_metrics/0_set_initial.rb +39 -0
  23. data/lib/karafka/web/management/migrations/consumers_metrics/1699543515_fill_missing_received_and_sent_bytes.rb +28 -0
  24. data/lib/karafka/web/management/migrations/consumers_metrics/1700234522_introduce_waiting.rb +26 -0
  25. data/lib/karafka/web/management/migrations/consumers_metrics/1700234522_remove_processing.rb +26 -0
  26. data/lib/karafka/web/management/migrations/consumers_metrics/1704722380_split_listeners_into_active_and_paused.rb +38 -0
  27. data/lib/karafka/web/management/migrations/consumers_metrics/1706607960_introduce_lag_total.rb +40 -0
  28. data/lib/karafka/web/management/migrations/consumers_metrics/1706611396_rename_lag_total_to_lag_hybrid.rb +38 -0
  29. data/lib/karafka/web/management/migrations/consumers_metrics/1716218393_populate_jobs_metrics.rb +26 -0
  30. data/lib/karafka/web/management/migrations/consumers_states/0_set_initial.rb +46 -0
  31. data/lib/karafka/web/management/migrations/consumers_states/1699543515_fill_missing_received_and_sent_bytes.rb +25 -0
  32. data/lib/karafka/web/management/migrations/consumers_states/1700234522_introduce_waiting.rb +22 -0
  33. data/lib/karafka/web/management/migrations/consumers_states/1700234522_remove_processing.rb +22 -0
  34. data/lib/karafka/web/management/migrations/consumers_states/1704722380_split_listeners_into_active_and_paused.rb +34 -0
  35. data/lib/karafka/web/management/migrations/consumers_states/1706607960_introduce_lag_total.rb +24 -0
  36. data/lib/karafka/web/management/migrations/consumers_states/1706611396_rename_lag_total_to_lag_hybrid.rb +23 -0
  37. data/lib/karafka/web/management/migrations/consumers_states/1716218393_add_jobs_counter.rb +24 -0
  38. data/lib/karafka/web/management/migrator.rb +5 -5
  39. data/lib/karafka/web/pro/commanding/commands/base.rb +8 -0
  40. data/lib/karafka/web/pro/commanding/commands/quiet.rb +4 -1
  41. data/lib/karafka/web/pro/commanding/commands/stop.rb +4 -1
  42. data/lib/karafka/web/pro/loader.rb +8 -0
  43. data/lib/karafka/web/pro/ui/app.rb +44 -7
  44. data/lib/karafka/web/pro/ui/controllers/dlq_controller.rb +1 -1
  45. data/lib/karafka/web/pro/ui/controllers/errors_controller.rb +1 -0
  46. data/lib/karafka/web/pro/ui/controllers/explorer_controller.rb +6 -14
  47. data/lib/karafka/web/pro/ui/controllers/messages_controller.rb +5 -4
  48. data/lib/karafka/web/pro/ui/controllers/search_controller.rb +73 -0
  49. data/lib/karafka/web/pro/ui/controllers/support_controller.rb +26 -0
  50. data/lib/karafka/web/pro/ui/controllers/topics_controller.rb +31 -0
  51. data/lib/karafka/web/pro/ui/controllers/ux_controller.rb +26 -0
  52. data/lib/karafka/web/pro/ui/lib/policies/config.rb +39 -0
  53. data/lib/karafka/web/pro/ui/lib/policies/contracts/config.rb +46 -0
  54. data/lib/karafka/web/pro/ui/lib/policies/messages.rb +76 -0
  55. data/lib/karafka/web/pro/ui/lib/policies/requests.rb +36 -0
  56. data/lib/karafka/web/pro/ui/lib/policies.rb +34 -0
  57. data/lib/karafka/web/pro/ui/lib/safe_runner.rb +98 -0
  58. data/lib/karafka/web/pro/ui/lib/search/config.rb +53 -0
  59. data/lib/karafka/web/pro/ui/lib/search/contracts/config.rb +101 -0
  60. data/lib/karafka/web/pro/ui/lib/search/contracts/form.rb +111 -0
  61. data/lib/karafka/web/pro/ui/lib/search/matchers/base.rb +59 -0
  62. data/lib/karafka/web/pro/ui/lib/search/matchers/raw_header_includes.rb +57 -0
  63. data/lib/karafka/web/pro/ui/lib/search/matchers/raw_key_includes.rb +41 -0
  64. data/lib/karafka/web/pro/ui/lib/search/matchers/raw_payload_includes.rb +45 -0
  65. data/lib/karafka/web/pro/ui/lib/search/normalizer.rb +47 -0
  66. data/lib/karafka/web/pro/ui/lib/search/runner.rb +230 -0
  67. data/lib/karafka/web/pro/ui/lib/search.rb +36 -0
  68. data/lib/karafka/web/pro/ui/views/cluster/_breadcrumbs.erb +4 -4
  69. data/lib/karafka/web/pro/ui/views/cluster/_tabs.erb +14 -24
  70. data/lib/karafka/web/pro/ui/views/cluster/index.erb +20 -22
  71. data/lib/karafka/web/pro/ui/views/cluster/show.erb +21 -25
  72. data/lib/karafka/web/pro/ui/views/commands/_backtrace.erb +4 -19
  73. data/lib/karafka/web/pro/ui/views/commands/_breadcrumbs.erb +3 -3
  74. data/lib/karafka/web/pro/ui/views/commands/_command.erb +6 -6
  75. data/lib/karafka/web/pro/ui/views/commands/_command_details.erb +1 -11
  76. data/lib/karafka/web/pro/ui/views/commands/_incompatible_schema.erb +3 -14
  77. data/lib/karafka/web/pro/ui/views/commands/_metadata.erb +33 -42
  78. data/lib/karafka/web/pro/ui/views/commands/_table.erb +9 -3
  79. data/lib/karafka/web/pro/ui/views/commands/index.erb +18 -12
  80. data/lib/karafka/web/pro/ui/views/commands/show.erb +24 -29
  81. data/lib/karafka/web/pro/ui/views/consumers/_breadcrumbs.erb +8 -8
  82. data/lib/karafka/web/pro/ui/views/consumers/_consumer.erb +13 -23
  83. data/lib/karafka/web/pro/ui/views/consumers/_consumer_controls.erb +51 -35
  84. data/lib/karafka/web/pro/ui/views/consumers/_consumer_performance.erb +1 -1
  85. data/lib/karafka/web/pro/ui/views/consumers/_tabs.erb +28 -30
  86. data/lib/karafka/web/pro/ui/views/consumers/consumer/_commands.erb +68 -28
  87. data/lib/karafka/web/pro/ui/views/consumers/consumer/_job.erb +1 -1
  88. data/lib/karafka/web/pro/ui/views/consumers/consumer/_metrics.erb +114 -133
  89. data/lib/karafka/web/pro/ui/views/consumers/consumer/_partition.erb +4 -4
  90. data/lib/karafka/web/pro/ui/views/consumers/consumer/_stopped.erb +6 -9
  91. data/lib/karafka/web/pro/ui/views/consumers/consumer/_subscription_group.erb +116 -126
  92. data/lib/karafka/web/pro/ui/views/consumers/consumer/_tabs.erb +26 -31
  93. data/lib/karafka/web/pro/ui/views/consumers/controls.erb +53 -57
  94. data/lib/karafka/web/pro/ui/views/consumers/details.erb +4 -17
  95. data/lib/karafka/web/pro/ui/views/consumers/index.erb +31 -34
  96. data/lib/karafka/web/pro/ui/views/consumers/pending_jobs.erb +41 -46
  97. data/lib/karafka/web/pro/ui/views/consumers/performance.erb +43 -47
  98. data/lib/karafka/web/pro/ui/views/consumers/running_jobs.erb +41 -46
  99. data/lib/karafka/web/pro/ui/views/consumers/subscriptions.erb +14 -17
  100. data/lib/karafka/web/pro/ui/views/dashboard/index.erb +67 -76
  101. data/lib/karafka/web/pro/ui/views/dlq/_breadcrumbs.erb +1 -1
  102. data/lib/karafka/web/pro/ui/views/dlq/_no_topics.erb +1 -7
  103. data/lib/karafka/web/pro/ui/views/dlq/_topic.erb +7 -10
  104. data/lib/karafka/web/pro/ui/views/dlq/index.erb +8 -10
  105. data/lib/karafka/web/pro/ui/views/errors/_breadcrumbs.erb +3 -3
  106. data/lib/karafka/web/pro/ui/views/errors/_error.erb +8 -5
  107. data/lib/karafka/web/pro/ui/views/errors/_selector.erb +12 -0
  108. data/lib/karafka/web/pro/ui/views/errors/_table.erb +5 -4
  109. data/lib/karafka/web/pro/ui/views/errors/index.erb +50 -15
  110. data/lib/karafka/web/pro/ui/views/errors/partition.erb +61 -14
  111. data/lib/karafka/web/pro/ui/views/errors/show.erb +28 -46
  112. data/lib/karafka/web/pro/ui/views/explorer/_breadcrumbs.erb +11 -3
  113. data/lib/karafka/web/pro/ui/views/explorer/_failed_deserialization.erb +8 -3
  114. data/lib/karafka/web/pro/ui/views/explorer/_message.erb +12 -6
  115. data/lib/karafka/web/pro/ui/views/explorer/_no_topics.erb +1 -5
  116. data/lib/karafka/web/pro/ui/views/explorer/_selector.erb +12 -0
  117. data/lib/karafka/web/pro/ui/views/explorer/_topic.erb +6 -8
  118. data/lib/karafka/web/pro/ui/views/explorer/index.erb +13 -15
  119. data/lib/karafka/web/pro/ui/views/explorer/message/_metadata.erb +68 -32
  120. data/lib/karafka/web/pro/ui/views/explorer/message/_payload.erb +17 -16
  121. data/lib/karafka/web/pro/ui/views/explorer/message/_resources_utilization.erb +127 -0
  122. data/lib/karafka/web/pro/ui/views/explorer/message/_too_big_to_be_displayed.erb +20 -0
  123. data/lib/karafka/web/pro/ui/views/explorer/messages/_detail.erb +1 -1
  124. data/lib/karafka/web/pro/ui/views/explorer/partition/_cleaned.erb +3 -5
  125. data/lib/karafka/web/pro/ui/views/explorer/partition/_empty.erb +3 -5
  126. data/lib/karafka/web/pro/ui/views/explorer/partition/_messages.erb +6 -3
  127. data/lib/karafka/web/pro/ui/views/explorer/partition.erb +67 -46
  128. data/lib/karafka/web/pro/ui/views/explorer/show.erb +85 -21
  129. data/lib/karafka/web/pro/ui/views/explorer/topic/_actions.erb +27 -0
  130. data/lib/karafka/web/pro/ui/views/explorer/topic/_empty.erb +3 -5
  131. data/lib/karafka/web/pro/ui/views/explorer/topic/_limited.erb +8 -10
  132. data/lib/karafka/web/pro/ui/views/explorer/topic.erb +24 -44
  133. data/lib/karafka/web/pro/ui/views/health/_breadcrumbs.erb +7 -7
  134. data/lib/karafka/web/pro/ui/views/health/_no_data.erb +1 -7
  135. data/lib/karafka/web/pro/ui/views/health/_partition.erb +3 -3
  136. data/lib/karafka/web/pro/ui/views/health/_partition_lags.erb +3 -3
  137. data/lib/karafka/web/pro/ui/views/health/_partition_offset.erb +2 -2
  138. data/lib/karafka/web/pro/ui/views/health/_partition_times.erb +3 -7
  139. data/lib/karafka/web/pro/ui/views/health/_table_metadata.erb +8 -0
  140. data/lib/karafka/web/pro/ui/views/health/_tabs.erb +32 -49
  141. data/lib/karafka/web/pro/ui/views/health/changes.erb +51 -51
  142. data/lib/karafka/web/pro/ui/views/health/cluster_lags.erb +28 -41
  143. data/lib/karafka/web/pro/ui/views/health/lags.erb +52 -52
  144. data/lib/karafka/web/pro/ui/views/health/offsets.erb +55 -55
  145. data/lib/karafka/web/pro/ui/views/health/overview.erb +60 -60
  146. data/lib/karafka/web/pro/ui/views/jobs/_job.erb +1 -1
  147. data/lib/karafka/web/pro/ui/views/jobs/_no_jobs.erb +1 -7
  148. data/lib/karafka/web/pro/ui/views/jobs/pending.erb +36 -38
  149. data/lib/karafka/web/pro/ui/views/jobs/running.erb +36 -38
  150. data/lib/karafka/web/pro/ui/views/routing/_consumer_group.erb +7 -12
  151. data/lib/karafka/web/pro/ui/views/routing/_topic.erb +13 -11
  152. data/lib/karafka/web/pro/ui/views/routing/index.erb +7 -9
  153. data/lib/karafka/web/pro/ui/views/routing/show.erb +41 -33
  154. data/lib/karafka/web/pro/ui/views/search/_fix_errors.erb +3 -0
  155. data/lib/karafka/web/pro/ui/views/search/_metadata.erb +71 -0
  156. data/lib/karafka/web/pro/ui/views/search/_no_results.erb +3 -0
  157. data/lib/karafka/web/pro/ui/views/search/_no_search_criteria.erb +5 -0
  158. data/lib/karafka/web/pro/ui/views/search/_search_criteria.erb +37 -0
  159. data/lib/karafka/web/pro/ui/views/search/_search_modal.erb +139 -0
  160. data/lib/karafka/web/pro/ui/views/search/_timeout.erb +3 -0
  161. data/lib/karafka/web/pro/ui/views/search/index.erb +29 -0
  162. data/lib/karafka/web/pro/ui/views/shared/_navigation.erb +80 -28
  163. data/lib/karafka/web/pro/ui/views/topics/_breadcrumbs.erb +14 -6
  164. data/lib/karafka/web/pro/ui/views/topics/_partition_offsets.erb +10 -0
  165. data/lib/karafka/web/pro/ui/views/topics/_tabs.erb +26 -32
  166. data/lib/karafka/web/pro/ui/views/topics/_topic.erb +7 -10
  167. data/lib/karafka/web/pro/ui/views/topics/config.erb +21 -25
  168. data/lib/karafka/web/pro/ui/views/topics/distribution/_badges.erb +10 -5
  169. data/lib/karafka/web/pro/ui/views/topics/distribution/_chart.erb +3 -1
  170. data/lib/karafka/web/pro/ui/views/topics/distribution/_limited.erb +1 -1
  171. data/lib/karafka/web/pro/ui/views/topics/distribution.erb +34 -39
  172. data/lib/karafka/web/pro/ui/views/topics/index.erb +13 -15
  173. data/lib/karafka/web/pro/ui/views/topics/offsets.erb +24 -0
  174. data/lib/karafka/web/pro/ui/views/topics/replication.erb +20 -24
  175. data/lib/karafka/web/processing/consumers/aggregators/metrics.rb +1 -1
  176. data/lib/karafka/web/processing/consumers/aggregators/state.rb +1 -1
  177. data/lib/karafka/web/processing/consumers/contracts/aggregated_stats.rb +1 -0
  178. data/lib/karafka/web/tracking/consumers/contracts/report.rb +6 -0
  179. data/lib/karafka/web/tracking/consumers/listeners/connections.rb +8 -6
  180. data/lib/karafka/web/tracking/consumers/listeners/processing.rb +2 -0
  181. data/lib/karafka/web/tracking/consumers/listeners/tags.rb +1 -1
  182. data/lib/karafka/web/tracking/consumers/reporter.rb +6 -8
  183. data/lib/karafka/web/tracking/consumers/sampler.rb +16 -5
  184. data/lib/karafka/web/ui/app.rb +20 -1
  185. data/lib/karafka/web/ui/base.rb +26 -20
  186. data/lib/karafka/web/ui/controllers/base_controller.rb +7 -5
  187. data/lib/karafka/web/ui/controllers/dashboard_controller.rb +8 -0
  188. data/lib/karafka/web/ui/controllers/requests/params.rb +16 -2
  189. data/lib/karafka/web/ui/controllers/support_controller.rb +17 -0
  190. data/lib/karafka/web/ui/controllers/ux_controller.rb +17 -0
  191. data/lib/karafka/web/ui/helpers/application_helper.rb +75 -42
  192. data/lib/karafka/web/ui/helpers/paths_helper.rb +24 -0
  193. data/lib/karafka/web/ui/helpers/tailwind_helper.rb +90 -0
  194. data/lib/karafka/web/ui/lib/sorter.rb +1 -1
  195. data/lib/karafka/web/ui/models/metrics/aggregated.rb +1 -0
  196. data/lib/karafka/web/ui/models/metrics/charts/topics.rb +36 -20
  197. data/lib/karafka/web/ui/models/status.rb +28 -1
  198. data/lib/karafka/web/ui/public/images/calendar.svg +3 -0
  199. data/lib/karafka/web/ui/public/javascripts/application.js +39 -15
  200. data/lib/karafka/web/ui/public/javascripts/application.min.js +64 -0
  201. data/lib/karafka/web/ui/public/javascripts/application.min.js.br +0 -0
  202. data/lib/karafka/web/ui/public/javascripts/application.min.js.gz +0 -0
  203. data/lib/karafka/web/ui/public/javascripts/charts/types/line.js +41 -9
  204. data/lib/karafka/web/ui/public/javascripts/components/btn_toggle_manager.js +37 -0
  205. data/lib/karafka/web/ui/public/javascripts/{live_poll.js → components/live_poll.js} +44 -8
  206. data/lib/karafka/web/ui/public/javascripts/{offset_datetime.js → components/offset_datetime.js} +1 -1
  207. data/lib/karafka/web/ui/public/javascripts/components/search.js +102 -0
  208. data/lib/karafka/web/ui/public/javascripts/components/tabs_manager.js +84 -0
  209. data/lib/karafka/web/ui/public/javascripts/components/theme_manager.js +59 -0
  210. data/lib/karafka/web/ui/public/javascripts/components/turbo_tracker.js +30 -0
  211. data/lib/karafka/web/ui/public/javascripts/libs/datepicker.js +2 -2
  212. data/lib/karafka/web/ui/public/javascripts/libs/turbo.js +6618 -0
  213. data/lib/karafka/web/ui/public/stylesheets/application.css +16 -113
  214. data/lib/karafka/web/ui/public/stylesheets/application.min.css +13 -0
  215. data/lib/karafka/web/ui/public/stylesheets/application.min.css.br +0 -0
  216. data/lib/karafka/web/ui/public/stylesheets/application.min.css.gz +0 -0
  217. data/lib/karafka/web/ui/public/stylesheets/libs/highlight_dark.min.css +8 -0
  218. data/lib/karafka/web/ui/public/stylesheets/libs/highlight_dark.min.css.br +0 -0
  219. data/lib/karafka/web/ui/public/stylesheets/libs/highlight_dark.min.css.gz +0 -0
  220. data/lib/karafka/web/ui/public/stylesheets/libs/highlight_light.min.css.br +0 -0
  221. data/lib/karafka/web/ui/public/stylesheets/libs/highlight_light.min.css.gz +0 -0
  222. data/lib/karafka/web/ui/public/stylesheets/libs/tailwind.css +391 -0
  223. data/lib/karafka/web/ui/views/cluster/_breadcrumbs.erb +3 -3
  224. data/lib/karafka/web/ui/views/cluster/_tabs.erb +14 -24
  225. data/lib/karafka/web/ui/views/cluster/brokers.erb +20 -22
  226. data/lib/karafka/web/ui/views/cluster/replication.erb +28 -32
  227. data/lib/karafka/web/ui/views/consumers/_assignments_badges.erb +1 -1
  228. data/lib/karafka/web/ui/views/consumers/_breadcrumbs.erb +5 -0
  229. data/lib/karafka/web/ui/views/consumers/_consumer.erb +9 -13
  230. data/lib/karafka/web/ui/views/consumers/_no_consumers.erb +2 -8
  231. data/lib/karafka/web/ui/views/consumers/_summary.erb +34 -45
  232. data/lib/karafka/web/ui/views/consumers/_tabs.erb +35 -0
  233. data/lib/karafka/web/ui/views/consumers/index.erb +31 -33
  234. data/lib/karafka/web/ui/views/dashboard/_counters.erb +76 -0
  235. data/lib/karafka/web/ui/views/dashboard/_feature_pro.erb +6 -2
  236. data/lib/karafka/web/ui/views/dashboard/_not_enough_data.erb +3 -15
  237. data/lib/karafka/web/ui/views/dashboard/_ranges_selector.erb +12 -12
  238. data/lib/karafka/web/ui/views/dashboard/index.erb +78 -52
  239. data/lib/karafka/web/ui/views/errors/_breadcrumbs.erb +2 -2
  240. data/lib/karafka/web/ui/views/errors/_detail.erb +1 -3
  241. data/lib/karafka/web/ui/views/errors/_error.erb +3 -5
  242. data/lib/karafka/web/ui/views/errors/index.erb +34 -44
  243. data/lib/karafka/web/ui/views/errors/show.erb +29 -47
  244. data/lib/karafka/web/ui/views/jobs/_breadcrumbs.erb +3 -3
  245. data/lib/karafka/web/ui/views/jobs/_job.erb +1 -1
  246. data/lib/karafka/web/ui/views/jobs/_no_jobs.erb +1 -7
  247. data/lib/karafka/web/ui/views/jobs/_tabs.erb +14 -24
  248. data/lib/karafka/web/ui/views/jobs/pending.erb +30 -32
  249. data/lib/karafka/web/ui/views/jobs/running.erb +30 -32
  250. data/lib/karafka/web/ui/views/layout.erb +37 -21
  251. data/lib/karafka/web/ui/views/routing/_breadcrumbs.erb +2 -2
  252. data/lib/karafka/web/ui/views/routing/_consumer_group.erb +7 -12
  253. data/lib/karafka/web/ui/views/routing/_topic.erb +3 -5
  254. data/lib/karafka/web/ui/views/routing/index.erb +7 -9
  255. data/lib/karafka/web/ui/views/routing/show.erb +30 -22
  256. data/lib/karafka/web/ui/views/shared/_become_pro.erb +8 -8
  257. data/lib/karafka/web/ui/views/shared/_brand.erb +2 -2
  258. data/lib/karafka/web/ui/views/shared/_breadcrumbs.erb +23 -0
  259. data/lib/karafka/web/ui/views/shared/_content.erb +2 -28
  260. data/lib/karafka/web/ui/views/shared/_controls.erb +15 -0
  261. data/lib/karafka/web/ui/views/shared/_flashes.erb +5 -7
  262. data/lib/karafka/web/ui/views/shared/_header.erb +14 -19
  263. data/lib/karafka/web/ui/views/shared/_navigation.erb +84 -28
  264. data/lib/karafka/web/ui/views/shared/_no_paginated_data.erb +5 -9
  265. data/lib/karafka/web/ui/views/shared/_pagination.erb +11 -11
  266. data/lib/karafka/web/ui/views/shared/_tab_nav.erb +4 -5
  267. data/lib/karafka/web/ui/views/shared/_title.erb +5 -0
  268. data/lib/karafka/web/ui/views/shared/alerts/_box_error.erb +15 -0
  269. data/lib/karafka/web/ui/views/shared/alerts/_box_info.erb +15 -0
  270. data/lib/karafka/web/ui/views/shared/alerts/_box_primary.erb +15 -0
  271. data/lib/karafka/web/ui/views/shared/alerts/_box_secondary.erb +15 -0
  272. data/lib/karafka/web/ui/views/shared/alerts/_box_success.erb +15 -0
  273. data/lib/karafka/web/ui/views/shared/alerts/_box_warning.erb +15 -0
  274. data/lib/karafka/web/ui/views/shared/alerts/_error.erb +4 -0
  275. data/lib/karafka/web/ui/views/shared/alerts/_info.erb +5 -2
  276. data/lib/karafka/web/ui/views/shared/alerts/_primary.erb +4 -0
  277. data/lib/karafka/web/ui/views/shared/alerts/_secondary.erb +4 -0
  278. data/lib/karafka/web/ui/views/shared/alerts/_success.erb +4 -0
  279. data/lib/karafka/web/ui/views/shared/alerts/_warning.erb +4 -0
  280. data/lib/karafka/web/ui/views/shared/charts/_line.erb +1 -1
  281. data/lib/karafka/web/ui/views/shared/exceptions/not_allowed.erb +14 -19
  282. data/lib/karafka/web/ui/views/shared/exceptions/not_found.erb +16 -21
  283. data/lib/karafka/web/ui/views/shared/exceptions/pro_only.erb +16 -28
  284. data/lib/karafka/web/ui/views/shared/icons/_arrow_down_on_square.erb +3 -0
  285. data/lib/karafka/web/ui/views/shared/icons/_arrow_down_tray.erb +3 -0
  286. data/lib/karafka/web/ui/views/shared/icons/_arrow_on_squares.erb +3 -0
  287. data/lib/karafka/web/ui/views/shared/icons/_arrow_path_rounded.erb +3 -0
  288. data/lib/karafka/web/ui/views/shared/icons/_arrow_uturn_right.erb +3 -0
  289. data/lib/karafka/web/ui/views/shared/icons/_arrows_right_left.erb +3 -0
  290. data/lib/karafka/web/ui/views/shared/icons/_blocks.erb +3 -0
  291. data/lib/karafka/web/ui/views/shared/icons/_book_open.erb +3 -0
  292. data/lib/karafka/web/ui/views/shared/icons/_bug.erb +3 -0
  293. data/lib/karafka/web/ui/views/shared/icons/_burger.erb +14 -0
  294. data/lib/karafka/web/ui/views/shared/icons/_calendar_days.erb +3 -0
  295. data/lib/karafka/web/ui/views/shared/icons/_chart_bar.erb +3 -0
  296. data/lib/karafka/web/ui/views/shared/icons/_check_badge.erb +3 -0
  297. data/lib/karafka/web/ui/views/shared/icons/_check_circle.erb +3 -0
  298. data/lib/karafka/web/ui/views/shared/icons/_circle_stack.erb +3 -0
  299. data/lib/karafka/web/ui/views/shared/icons/_cpu.erb +3 -0
  300. data/lib/karafka/web/ui/views/shared/icons/_document_glass.erb +3 -0
  301. data/lib/karafka/web/ui/views/shared/icons/_exclamation_triangle.erb +3 -0
  302. data/lib/karafka/web/ui/views/shared/icons/_eye.erb +4 -0
  303. data/lib/karafka/web/ui/views/shared/icons/_gear.erb +4 -0
  304. data/lib/karafka/web/ui/views/shared/icons/_github.erb +13 -0
  305. data/lib/karafka/web/ui/views/shared/icons/_globe.erb +3 -0
  306. data/lib/karafka/web/ui/views/shared/icons/_heart.erb +3 -0
  307. data/lib/karafka/web/ui/views/shared/icons/_home.erb +3 -0
  308. data/lib/karafka/web/ui/views/shared/icons/_info_circle.erb +3 -0
  309. data/lib/karafka/web/ui/views/shared/icons/_lifebuoy.erb +3 -0
  310. data/lib/karafka/web/ui/views/shared/icons/_light_bulb.erb +3 -0
  311. data/lib/karafka/web/ui/views/shared/icons/_list_bullets.erb +3 -0
  312. data/lib/karafka/web/ui/views/shared/icons/_magnifying_glass.erb +3 -0
  313. data/lib/karafka/web/ui/views/shared/icons/_moon.erb +3 -0
  314. data/lib/karafka/web/ui/views/shared/icons/_offices.erb +3 -0
  315. data/lib/karafka/web/ui/views/shared/icons/_pause.erb +3 -0
  316. data/lib/karafka/web/ui/views/shared/icons/_pause_circle.erb +3 -0
  317. data/lib/karafka/web/ui/views/shared/icons/_play_circle.erb +4 -0
  318. data/lib/karafka/web/ui/views/shared/icons/_question_circle.erb +3 -0
  319. data/lib/karafka/web/ui/views/shared/icons/_queue_list.erb +3 -0
  320. data/lib/karafka/web/ui/views/shared/icons/_refresh.erb +3 -0
  321. data/lib/karafka/web/ui/views/shared/icons/_slack.erb +16 -0
  322. data/lib/karafka/web/ui/views/shared/icons/_stop.erb +3 -0
  323. data/lib/karafka/web/ui/views/shared/icons/_sun.erb +3 -0
  324. data/lib/karafka/web/ui/views/shared/icons/_x_circle.erb +3 -0
  325. data/lib/karafka/web/ui/views/shared/icons/_x_mark.erb +3 -0
  326. data/lib/karafka/web/ui/views/status/_breadcrumbs.erb +1 -1
  327. data/lib/karafka/web/ui/views/status/_failure.erb +2 -13
  328. data/lib/karafka/web/ui/views/status/_halted.erb +2 -10
  329. data/lib/karafka/web/ui/views/status/_info.erb +2 -13
  330. data/lib/karafka/web/ui/views/status/_success.erb +2 -10
  331. data/lib/karafka/web/ui/views/status/_warning.erb +2 -13
  332. data/lib/karafka/web/ui/views/status/failures/_connection.erb +2 -2
  333. data/lib/karafka/web/ui/views/status/failures/_consumers_reports.erb +3 -3
  334. data/lib/karafka/web/ui/views/status/failures/_consumers_reports_schema_state.erb +4 -4
  335. data/lib/karafka/web/ui/views/status/failures/_enabled.erb +2 -2
  336. data/lib/karafka/web/ui/views/status/failures/_initial_consumers_metrics.erb +6 -6
  337. data/lib/karafka/web/ui/views/status/failures/_initial_consumers_state.erb +6 -6
  338. data/lib/karafka/web/ui/views/status/failures/_live_reporting.erb +2 -2
  339. data/lib/karafka/web/ui/views/status/failures/_materializing_lag.erb +11 -0
  340. data/lib/karafka/web/ui/views/status/failures/_partitions.erb +3 -3
  341. data/lib/karafka/web/ui/views/status/failures/_state_calculation.erb +2 -2
  342. data/lib/karafka/web/ui/views/status/failures/_topics.erb +3 -3
  343. data/lib/karafka/web/ui/views/status/info/_components.erb +14 -41
  344. data/lib/karafka/web/ui/views/status/show.erb +165 -154
  345. data/lib/karafka/web/ui/views/status/warnings/_connection.erb +3 -3
  346. data/lib/karafka/web/ui/views/status/warnings/_pro_subscription.erb +2 -2
  347. data/lib/karafka/web/ui/views/status/warnings/_replication.erb +2 -2
  348. data/lib/karafka/web/ui/views/status/warnings/_routing_topics_presence.erb +1 -1
  349. data/lib/karafka/web/ui/views/support/_breadcrumbs.erb +5 -0
  350. data/lib/karafka/web/ui/views/support/show.erb +71 -0
  351. data/lib/karafka/web/ui/views/ux/_alerts.erb +25 -0
  352. data/lib/karafka/web/ui/views/ux/_badges.erb +21 -0
  353. data/lib/karafka/web/ui/views/ux/_breadcrumbs.erb +5 -0
  354. data/lib/karafka/web/ui/views/ux/_buttons.erb +47 -0
  355. data/lib/karafka/web/ui/views/ux/_card_detail.erb +15 -0
  356. data/lib/karafka/web/ui/views/ux/_card_metric.erb +123 -0
  357. data/lib/karafka/web/ui/views/ux/_card_summary.erb +72 -0
  358. data/lib/karafka/web/ui/views/ux/_card_support.erb +39 -0
  359. data/lib/karafka/web/ui/views/ux/_code.erb +9 -0
  360. data/lib/karafka/web/ui/views/ux/_data_table.erb +52 -0
  361. data/lib/karafka/web/ui/views/ux/_headers.erb +2 -0
  362. data/lib/karafka/web/ui/views/ux/_icons.erb +9 -0
  363. data/lib/karafka/web/ui/views/ux/_pagination.erb +32 -0
  364. data/lib/karafka/web/ui/views/ux/_row_table.erb +52 -0
  365. data/lib/karafka/web/ui/views/ux/_status_rows.erb +53 -0
  366. data/lib/karafka/web/ui/views/ux/_tabs.erb +14 -0
  367. data/lib/karafka/web/ui/views/ux/_text.erb +2 -0
  368. data/lib/karafka/web/ui/views/ux/_topic_tiles.erb +42 -0
  369. data/lib/karafka/web/ui/views/ux/show.erb +19 -0
  370. data/lib/karafka/web/version.rb +1 -1
  371. data/lib/karafka/web.rb +2 -0
  372. data/package-lock.json +4158 -0
  373. data/package.json +15 -0
  374. data/postcss.config.js +6 -0
  375. data/tailwind.config.js +16 -0
  376. data.tar.gz.sig +0 -0
  377. metadata +172 -47
  378. metadata.gz.sig +0 -0
  379. data/lib/karafka/web/management/migrations/0_set_initial_consumers_metrics.rb +0 -36
  380. data/lib/karafka/web/management/migrations/0_set_initial_consumers_state.rb +0 -43
  381. data/lib/karafka/web/management/migrations/1699543515_fill_missing_received_and_sent_bytes_in_consumers_metrics.rb +0 -26
  382. data/lib/karafka/web/management/migrations/1699543515_fill_missing_received_and_sent_bytes_in_consumers_state.rb +0 -23
  383. data/lib/karafka/web/management/migrations/1700234522_introduce_waiting_in_consumers_metrics.rb +0 -24
  384. data/lib/karafka/web/management/migrations/1700234522_introduce_waiting_in_consumers_state.rb +0 -20
  385. data/lib/karafka/web/management/migrations/1700234522_remove_processing_from_consumers_metrics.rb +0 -24
  386. data/lib/karafka/web/management/migrations/1700234522_remove_processing_from_consumers_state.rb +0 -20
  387. data/lib/karafka/web/management/migrations/1704722380_split_listeners_into_active_and_paused_in_metrics.rb +0 -36
  388. data/lib/karafka/web/management/migrations/1704722380_split_listeners_into_active_and_paused_in_states.rb +0 -32
  389. data/lib/karafka/web/management/migrations/1706607960_introduce_lag_total_in_metrics.rb +0 -38
  390. data/lib/karafka/web/management/migrations/1706607960_introduce_lag_total_in_states.rb +0 -22
  391. data/lib/karafka/web/management/migrations/1706611396_rename_lag_total_to_lag_hybrid_in_metrics.rb +0 -36
  392. data/lib/karafka/web/management/migrations/1706611396_rename_lag_total_to_lag_hybrid_in_states.rb +0 -21
  393. data/lib/karafka/web/pro/ui/views/cluster/brokers.erb +0 -27
  394. data/lib/karafka/web/pro/ui/views/commands/_details.erb +0 -26
  395. data/lib/karafka/web/pro/ui/views/consumers/_counters.erb +0 -72
  396. data/lib/karafka/web/pro/ui/views/consumers/consumer/_title.erb +0 -5
  397. data/lib/karafka/web/pro/ui/views/errors/_title_with_select.erb +0 -31
  398. data/lib/karafka/web/pro/ui/views/explorer/message/_message_actions.erb +0 -18
  399. data/lib/karafka/web/pro/ui/views/explorer/message/_payload_actions.erb +0 -19
  400. data/lib/karafka/web/pro/ui/views/explorer/partition/_details.erb +0 -35
  401. data/lib/karafka/web/pro/ui/views/explorer/topic/_details.erb +0 -23
  402. data/lib/karafka/web/pro/ui/views/health/_consumer_group_header.erb +0 -14
  403. data/lib/karafka/web/ui/controllers/responses/deny.rb +0 -15
  404. data/lib/karafka/web/ui/helpers/alerts_helper.rb +0 -23
  405. data/lib/karafka/web/ui/lib/safe_runner.rb +0 -59
  406. data/lib/karafka/web/ui/models/visibility_filter.rb +0 -49
  407. data/lib/karafka/web/ui/public/javascripts/libs/bootstrap.min.js +0 -6
  408. data/lib/karafka/web/ui/public/javascripts/tabs_manager.js +0 -57
  409. data/lib/karafka/web/ui/public/stylesheets/libs/bootstrap.min.css +0 -6
  410. data/lib/karafka/web/ui/views/consumers/_counters.erb +0 -62
  411. data/lib/karafka/web/ui/views/errors/_watermark_offsets.erb +0 -10
  412. data/lib/karafka/web/ui/views/shared/_feature_pro.erb +0 -4
  413. data/lib/karafka/web/ui/views/shared/_footer.erb +0 -22
  414. data/lib/karafka/web/ui/views/shared/_live_poll.erb +0 -7
  415. /data/lib/karafka/web/management/migrations/{0_base.rb → base.rb} +0 -0
  416. /data/lib/karafka/web/ui/public/javascripts/{charts.js → components/charts.js} +0 -0
  417. /data/lib/karafka/web/ui/public/stylesheets/libs/{highlight.min.css → highlight_light.min.css} +0 -0
@@ -0,0 +1,230 @@
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 Lib
19
+ module Search
20
+ # Search runner that selects proper matcher, sets the parameters and runs the search
21
+ # We use the Pro Iterator for searching but this runner adds metadata tracking and
22
+ # some other metrics that are useful in the Web UI
23
+ #
24
+ # @note When running a search from latest, we stop when message timestamp is higher
25
+ # then the time when lookup started. This prevents us from iterating on topics for
26
+ # an extended time period when there are less messages than the requested amount but
27
+ # new are coming in real time. It acts as a virtual "eof".
28
+ class Runner
29
+ include Karafka::Core::Helpers::Time
30
+
31
+ # Metrics we collect during search for each partition + totals
32
+ METRICS_BASE = {
33
+ first_message: false,
34
+ last_message: false,
35
+ checked: 0,
36
+ matched: 0
37
+ }.freeze
38
+
39
+ # Fields that we use that come from the search query
40
+ # Those fields are aliased here for cleaner code so we don't have to reference them
41
+ # from the hash each time they are needed
42
+ SEARCH_CRITERIA_FIELDS = %i[
43
+ matcher
44
+ limit
45
+ offset
46
+ offset_type
47
+ partitions
48
+ phrase
49
+ timestamp
50
+ ].freeze
51
+
52
+ private_constant :METRICS_BASE, :SEARCH_CRITERIA_FIELDS
53
+
54
+ # @param topic [String] topic in which we want to search
55
+ # @param partitions_count [Integer] how many partitions this topic has
56
+ # @param search_criteria [Hash] normalized search criteria
57
+ def initialize(topic, partitions_count, search_criteria)
58
+ @topic = topic
59
+ @partitions_count = partitions_count
60
+ @search_criteria = search_criteria
61
+ @partitions_stats = Hash.new { |h, k| h[k] = METRICS_BASE.dup }
62
+ @totals_stats = METRICS_BASE.dup
63
+ @timeout = Web.config.ui.search.timeout
64
+ @stop_reason = nil
65
+ @matched = []
66
+ end
67
+
68
+ # Runs the search, collects search statistics and returns the results
69
+ # @return [Array<Array<Karafka::Messages::Message>, Hash>] array with search results
70
+ # and metadata
71
+ # @note Results are sorted based on the time value.
72
+ def call
73
+ search_with_stats
74
+
75
+ [
76
+ # We return most recent results on top
77
+ @matched.sort_by(&:timestamp).reverse,
78
+ {
79
+ totals: @totals_stats,
80
+ partitions: @partitions_stats,
81
+ stop_reason: @stop_reason
82
+ }.freeze
83
+ ]
84
+ end
85
+
86
+ private
87
+
88
+ SEARCH_CRITERIA_FIELDS.each do |q|
89
+ class_eval <<~RUBY, __FILE__, __LINE__ + 1
90
+ def #{q}
91
+ @#{q} ||= @search_criteria.fetch(:#{q})
92
+ end
93
+ RUBY
94
+ end
95
+
96
+ # @return [#call] Finds and builds the lookup matcher
97
+ # @note We create one instance for all matchings in a single search. That way in case
98
+ # someone would want a stateful matcher, this can be done.
99
+ def current_matcher
100
+ return @current_matcher if @current_matcher
101
+
102
+ found_matcher_class = Web.config.ui.search.matchers.find do |matcher_class|
103
+ # Search only in active matchers for the current topic
104
+ matcher_class.active?(@topic) && matcher_class.name == matcher
105
+ end
106
+
107
+ # This should never happen. Report if you encounter this
108
+ found_matcher_class || raise(Karafka::Errors::UnsupportedCaseError, matcher)
109
+
110
+ @current_matcher = found_matcher_class.new
111
+ end
112
+
113
+ # @return [Karafka::Pro::Iterator]
114
+ def iterator
115
+ return @iterator if @iterator
116
+
117
+ # Establish starting point
118
+ start = case offset_type
119
+ when 'latest'
120
+ (limit / partitions_to_search.size) * -1
121
+ when 'offset'
122
+ offset
123
+ when 'timestamp'
124
+ # Kafka timestamp of message is in ms, we need a second precision for
125
+ # `Time#at`
126
+ Time.at(timestamp / 1_000.to_f)
127
+ else
128
+ # This should never happen. Contact us if you see this.
129
+ raise ::Karafka::Errors::UnsupportedCaseError, offset_type
130
+ end
131
+
132
+ iterator_query = {
133
+ @topic => partitions_to_search.map { |par| [par, start] }.to_h
134
+ }
135
+
136
+ @iterator = Karafka::Pro::Iterator.new(iterator_query)
137
+ end
138
+
139
+ # Runs the search, measures its time and collects needed metrics
140
+ # It uses the selected search matcher.
141
+ def search_with_stats
142
+ started_at = monotonic_now
143
+ started_at_time = Time.now
144
+
145
+ per_partition = (limit / partitions_to_search.size)
146
+ # Ensure that in case we have a limit smaller than number of partitions, we check
147
+ # at least one message (if any) per partition
148
+ per_partition = 1 if per_partition.zero?
149
+
150
+ iterator.each do |message|
151
+ @current_partition = message.partition
152
+
153
+ # If we reached the total limit of messages we should check per request
154
+ # If we are running search for too long, we should also stop. This prevents
155
+ # a case where slow matcher would cause Web UI to hang and never finish
156
+ if @totals_stats[:checked] >= limit
157
+ @stop_reason = :limit
158
+ iterator.stop
159
+ next
160
+ end
161
+
162
+ if (monotonic_now - started_at) > @timeout
163
+ @stop_reason = :timeout
164
+ iterator.stop
165
+ next
166
+ end
167
+
168
+ # If we checked enough per this partition or we reached the current time we
169
+ # should stop. We do not go beyond the moment if time of the moment when
170
+ # the lookup started to prevent endless lookups on partitions that have a lot
171
+ # of messages being written to them in real time
172
+ if current_stats[:checked] >= per_partition ||
173
+ message.timestamp > started_at_time
174
+ iterator.stop_current_partition
175
+ next
176
+ end
177
+
178
+ @totals_stats[:checked] += 1
179
+ current_stats[:checked] += 1
180
+ current_stats[:first_message] ||= message
181
+ current_stats[:last_message] = message
182
+
183
+ if current_matcher.call(message, phrase)
184
+ @matched << message
185
+
186
+ current_stats[:matched] += 1
187
+ @totals_stats[:matched] += 1
188
+ end
189
+
190
+ message.clean!
191
+ end
192
+
193
+ @stop_reason ||= :eof
194
+
195
+ iterator.stop
196
+
197
+ @totals_stats[:time_taken] = monotonic_now - started_at
198
+ end
199
+
200
+ # @return [Hash] statistics of the partition for which message we're currently
201
+ # checking.
202
+ def current_stats
203
+ @partitions_stats[@current_partition]
204
+ end
205
+
206
+ # @return [Array<Integer>] partitions in which we're supposed to search
207
+ def partitions_to_search
208
+ return @partitions_to_search if @partitions_to_search
209
+
210
+ # Lets start with assumption that we search in all the partitions
211
+ @partitions_to_search = (0...@partitions_count).to_a
212
+
213
+ # If in the search query there is no "all", we pick only partitions that do exist
214
+ # in the topic that were part of the requested search scope
215
+ unless partitions.include?('all')
216
+ @partitions_to_search &= partitions.map(&:to_i)
217
+ # and just in case someone would provide really weird data, we fallback to
218
+ # partition 0
219
+ @partitions_to_search = [0] if @partitions_to_search.empty?
220
+ end
221
+
222
+ @partitions_to_search
223
+ end
224
+ end
225
+ end
226
+ end
227
+ end
228
+ end
229
+ end
230
+ end
@@ -0,0 +1,36 @@
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 Lib
19
+ # All code needed to support the search functionality
20
+ # It's not in models because it does not provide "data" per se but rather fetches it
21
+ # from a Kafka.
22
+ module Search
23
+ class << self
24
+ # Validates that the UI search config is correct
25
+ #
26
+ # @param config [Karafka::Core::Configurable::Node] web config
27
+ def post_setup(config)
28
+ Search::Contracts::Config.new.validate!(config.to_h)
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -1,11 +1,11 @@
1
- <li class="breadcrumb-item">
1
+ <li>
2
2
  <a href="<%= root_path('cluster') %>">
3
3
  Cluster informations
4
4
  </a>
5
5
  </li>
6
6
 
7
7
  <% unless @partitions %>
8
- <li class="breadcrumb-item">
8
+ <li>
9
9
  <a href="<%= root_path('cluster') %>">
10
10
  Brokers
11
11
  </a>
@@ -13,7 +13,7 @@
13
13
  <% end %>
14
14
 
15
15
  <% if @broker %>
16
- <li class="breadcrumb-item">
16
+ <li>
17
17
  <a href="<%= root_path('cluster', @broker.id) %>">
18
18
  <%= @broker.full_name %>
19
19
  </a>
@@ -21,7 +21,7 @@
21
21
  <% end %>
22
22
 
23
23
  <% if @partitions %>
24
- <li class="breadcrumb-item">
24
+ <li>
25
25
  <a href="<%= root_path('cluster', 'replication') %>">
26
26
  Replication
27
27
  </a>
@@ -1,27 +1,17 @@
1
- <div class="container">
2
- <div class="row mb-4">
3
- <div class="col-sm-12">
1
+ <div class="tab-container-wrapper">
2
+ <div class="tab-container">
3
+ <a
4
+ href="<%= root_path('cluster') %>"
5
+ class="custom-tab <%= nav_class(end_with: 'cluster') %>"
6
+ >
7
+ Brokers
8
+ </a>
4
9
 
5
- <ul class="nav nav-tabs">
6
- <li class="nav-item">
7
- <a
8
- class="nav-link <%= nav_class(end_with: 'cluster') %>"
9
- href="<%= root_path('cluster') %>"
10
- >
11
- Brokers
12
- </a>
13
- </li>
14
-
15
- <li class="nav-item">
16
- <a
17
- class="nav-link <%= nav_class(include: 'replication') %>"
18
- href="<%= root_path('cluster', 'replication') %>"
19
- >
20
- Replication
21
- </a>
22
- </li>
23
- </ul>
24
-
25
- </div>
10
+ <a
11
+ href="<%= root_path('cluster', 'replication') %>"
12
+ class="custom-tab <%= nav_class(include: 'replication') %>"
13
+ >
14
+ Replication
15
+ </a>
26
16
  </div>
27
17
  </div>
@@ -1,27 +1,25 @@
1
- <%== view_title('Cluster Informations', hr: false) %>
1
+ <% view_title 'Cluster Informations' %>
2
2
 
3
3
  <%== partial 'cluster/tabs' %>
4
4
 
5
- <div class="container mb-5">
6
- <div class="row">
7
- <div class="col-lg-12 table-responsive">
8
- <table class="processes bg-white table table-hover table-bordered table-striped">
9
- <thead>
10
- <tr class="align-middle">
11
- <th><%== sort_link(:id) %></th>
12
- <th><%== sort_link(:name) %></th>
13
- <th><%== sort_link(:port) %></th>
14
- </tr>
15
- </thead>
16
- <tbody>
17
- <%==
18
- each_partial(
19
- @brokers,
20
- 'cluster/broker'
21
- )
22
- %>
23
- </tbody>
24
- </table>
25
- </div>
5
+ <div class="col-span-12 mb-3">
6
+ <div class="data-table-wrapper">
7
+ <table class="data-table">
8
+ <thead>
9
+ <tr>
10
+ <th><%== sort_link(:id) %></th>
11
+ <th><%== sort_link(:name) %></th>
12
+ <th><%== sort_link(:port) %></th>
13
+ </tr>
14
+ </thead>
15
+ <tbody>
16
+ <%==
17
+ each_partial(
18
+ @brokers,
19
+ 'cluster/broker'
20
+ )
21
+ %>
22
+ </tbody>
23
+ </table>
26
24
  </div>
27
25
  </div>
@@ -1,27 +1,23 @@
1
- <%== view_title(@broker.full_name, hr: true) %>
1
+ <% view_title @broker.full_name %>
2
2
 
3
- <div class="container mb-5">
4
- <div class="row">
5
- <div class="col-lg-12 table-responsive">
6
- <table class="processes bg-white table table-hover table-bordered table-striped">
7
- <thead>
8
- <tr class="align-middle">
9
- <th><%== sort_link(:name) %></th>
10
- <th><%== sort_link(:value) %></th>
11
- <th><%== sort_link(:default?) %></th>
12
- <th><%== sort_link(:sensitive?) %></th>
13
- <th><%== sort_link(:read_only?) %></th>
14
- </tr>
15
- </thead>
16
- <tbody>
17
- <%==
18
- each_partial(
19
- @configs,
20
- 'cluster/config'
21
- )
22
- %>
23
- </tbody>
24
- </table>
25
- </div>
26
- </div>
3
+ <div class="data-table-wrapper">
4
+ <table class="data-table">
5
+ <thead>
6
+ <tr>
7
+ <th><%== sort_link(:name) %></th>
8
+ <th><%== sort_link(:value) %></th>
9
+ <th><%== sort_link(:default?) %></th>
10
+ <th><%== sort_link(:sensitive?) %></th>
11
+ <th><%== sort_link(:read_only?) %></th>
12
+ </tr>
13
+ </thead>
14
+ <tbody>
15
+ <%==
16
+ each_partial(
17
+ @configs,
18
+ 'cluster/config'
19
+ )
20
+ %>
21
+ </tbody>
22
+ </table>
27
23
  </div>
@@ -1,20 +1,5 @@
1
- <div class="container">
2
- <div class="row mb-4">
3
- <div class="col-sm-12">
4
- <h5 class="mb-2">
5
- <%= backtrace[:label] %>
6
- </h5>
7
- <hr/>
8
- </div>
9
- </div>
1
+ <h3 class="h3 mt-6">
2
+ <%= backtrace[:label] %>
3
+ </h3>
10
4
 
11
- <div class="row mb-5">
12
- <div class="col-sm-12">
13
- <div class="card">
14
- <div class="card-body">
15
- <pre class="m-0 p-0"><code class="wrapped json p-0 m-0"><%= backtrace[:backtrace] %></code></pre>
16
- </div>
17
- </div>
18
- </div>
19
- </div>
20
- </div>
5
+ <pre class="code"><code class="wrapped json p-0 m-0"><%= backtrace[:backtrace] %></code></pre>
@@ -1,11 +1,11 @@
1
- <li class="breadcrumb-item">
1
+ <li>
2
2
  <a href="<%= root_path('consumers/overview') %>">
3
3
  Consumers
4
4
  </a>
5
5
  </li>
6
6
 
7
7
  <% if current_path.include?('/commands') %>
8
- <li class="breadcrumb-item">
8
+ <li>
9
9
  <a href="<%= root_path('commands') %>">
10
10
  Commands
11
11
  </a>
@@ -13,7 +13,7 @@
13
13
  <% end %>
14
14
 
15
15
  <% if @command_message %>
16
- <li class="breadcrumb-item">
16
+ <li>
17
17
  <a href="<%= root_path('commands', @command_message.offset) %>">
18
18
  <%= @command_message.offset %>
19
19
  </a>
@@ -7,7 +7,7 @@
7
7
  <tr>
8
8
  <td>
9
9
  <% color = command[:type] == 'result' ? 'success' : 'primary' %>
10
- <span class="badge bg-<%= color %> badge-topic">
10
+ <span class="badge badge-<%= color %>">
11
11
  <%= command[:type] %>
12
12
  </span>
13
13
  </td>
@@ -16,16 +16,16 @@
16
16
  <%
17
17
  color = case command[:command][:name]
18
18
  when 'probe'
19
- 'secondary'
19
+ 'info'
20
20
  when 'quiet'
21
21
  'warning'
22
22
  when 'stop'
23
- 'danger'
23
+ 'error'
24
24
  else
25
25
  'secondary'
26
26
  end
27
27
  %>
28
- <span class="badge bg-<%= color %> badge-topic">
28
+ <span class="badge badge-<%= color %>">
29
29
  <%= command[:command][:name] %>
30
30
  </span>
31
31
  </td>
@@ -44,8 +44,8 @@
44
44
  <%== relative_time command[:dispatched_at] %>
45
45
  </td>
46
46
 
47
- <td class="text-center">
48
- <a href="<%= root_path('commands', command_message.offset) %>" class="btn btn-sm btn-secondary text-white">
47
+ <td>
48
+ <a href="<%= root_path('commands', command_message.offset) %>" class="btn btn-sm btn-primary">
49
49
  Details
50
50
  </a>
51
51
  </td>
@@ -1,11 +1 @@
1
- <div class="container">
2
- <div class="row mb-5">
3
- <div class="col-sm-12">
4
- <div class="card">
5
- <div class="card-body">
6
- <pre class="m-0 p-0"><code class="wrapped json p-0 m-0"><%= JSON.pretty_generate command %></code></pre>
7
- </div>
8
- </div>
9
- </div>
10
- </div>
11
- </div>
1
+ <pre class="code"><code class="json"><%= JSON.pretty_generate command %></code></pre>
@@ -1,14 +1,3 @@
1
- <div class="container">
2
- <div class="row mb-5">
3
- <div class="col-sm-12">
4
-
5
- <div class="alert alert-danger" role="alert">
6
- <h4 class="alert-heading">Incompatible Command Schema</h4>
7
- <p class="mb-1">
8
- This issue occurs when the Web UI and consumer processes use different command schemas, preventing the display of command details. It arises from version mismatches, where either the Web UI or the consumer processes are outdated. To resolve this, ensure both components use compatible versions with the same schema.
9
- </p>
10
- </div>
11
-
12
- </div>
13
- </div>
14
- </div>
1
+ <% alert_box_error('Incompatible Command Schema') do %>
2
+ This issue occurs when the Web UI and consumer processes use different command schemas, preventing the display of command details. It arises from version mismatches, where either the Web UI or the consumer processes are outdated. To resolve this, ensure both components use compatible versions with the same schema.
3
+ <% end %>
@@ -2,49 +2,40 @@
2
2
  process_id = command[:process][:id]
3
3
  %>
4
4
 
5
- <div class="container">
6
- <div class="row mb-4">
7
- <div class="col-sm-12">
8
- <h4 class="mb-2">
9
- Metadata
10
- </h4>
11
- <hr/>
12
- </div>
13
- </div>
5
+ <h2 class="h2">
6
+ Metadata
7
+ </h2>
14
8
 
15
- <div class="row mb-5">
16
- <div class="col-sm-12 table-responsive">
17
- <table class="processes bg-white table table-hover table-bordered table-striped mb-0 align-middle">
18
- <tbody>
19
- <tr>
20
- <td>Type</td>
21
- <td><%== command[:type] %></td>
22
- </tr>
9
+ <div class="data-table-wrapper">
10
+ <table class="data-table">
11
+ <tbody>
12
+ <tr>
13
+ <td>Type</td>
14
+ <td><%== command[:type] %></td>
15
+ </tr>
23
16
 
24
- <tr>
25
- <td>Name</td>
26
- <td><%== command[:command][:name] %></td>
27
- </tr>
17
+ <tr>
18
+ <td>Name</td>
19
+ <td><%== command[:command][:name] %></td>
20
+ </tr>
28
21
 
29
- <tr>
30
- <td>Dispatched</td>
31
- <td><%== relative_time command[:dispatched_at] %></td>
32
- </tr>
33
- <tr>
34
- <td>Process</td>
35
- <td>
36
- <% command = command %>
37
- <% if process_id == '*' %>
38
- <%= process_id %>
39
- <% else %>
40
- <a href="<%= root_path('consumers', process_id, 'subscriptions') %>">
41
- <%= process_id %>
42
- </a>
43
- <% end %>
44
- </td>
45
- </tr>
46
- </tbody>
47
- </table>
48
- </div>
49
- </div>
22
+ <tr>
23
+ <td>Dispatched</td>
24
+ <td><%== relative_time command[:dispatched_at] %></td>
25
+ </tr>
26
+ <tr>
27
+ <td>Process</td>
28
+ <td>
29
+ <% command = command %>
30
+ <% if process_id == '*' %>
31
+ <%= process_id %>
32
+ <% else %>
33
+ <a href="<%= root_path('consumers', process_id, 'subscriptions') %>">
34
+ <%= process_id %>
35
+ </a>
36
+ <% end %>
37
+ </td>
38
+ </tr>
39
+ </tbody>
40
+ </table>
50
41
  </div>
@@ -1,7 +1,7 @@
1
- <div class="table-responsive">
2
- <table class="processes bg-white table table-hover table-bordered table-striped mb-0 align-middle">
1
+ <div class="data-table-wrapper">
2
+ <table class="data-table">
3
3
  <thead>
4
- <tr class="align-middle">
4
+ <tr>
5
5
  <th>Type</th>
6
6
  <th>Name</th>
7
7
  <th>ID</th>
@@ -20,4 +20,10 @@
20
20
  %>
21
21
  </tbody>
22
22
  </table>
23
+
24
+ <p class="table_metadata">
25
+ Watermark offsets:
26
+ <%== badge_secondary "high: #{@watermark_offsets.high}" %>
27
+ <%== badge_secondary "low: #{@watermark_offsets.low}" %>
28
+ </p>
23
29
  </div>