karafka-web 0.11.0.beta1 → 0.11.0.beta3

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 (34) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +2 -1
  3. data/Gemfile.lock +1 -1
  4. data/Rakefile +4 -0
  5. data/karafka-web.gemspec +0 -5
  6. data/lib/karafka/web/errors.rb +0 -12
  7. data/lib/karafka/web/pro/ui/controllers/consumers/consumers_controller.rb +1 -3
  8. data/lib/karafka/web/pro/ui/views/consumers/consumers/_consumer.erb +47 -56
  9. data/lib/karafka/web/pro/ui/views/consumers/consumers/_consumer_performance.erb +59 -68
  10. data/lib/karafka/web/pro/ui/views/consumers/controls/_controls.erb +82 -91
  11. data/lib/karafka/web/pro/ui/views/jobs/_job.erb +38 -47
  12. data/lib/karafka/web/processing/consumer.rb +7 -7
  13. data/lib/karafka/web/processing/consumers/aggregators/state.rb +14 -14
  14. data/lib/karafka/web/ui/base.rb +1 -5
  15. data/lib/karafka/web/ui/models/process.rb +3 -1
  16. data/lib/karafka/web/ui/models/processes.rb +27 -6
  17. data/lib/karafka/web/ui/models/status.rb +1 -1
  18. data/lib/karafka/web/ui/public/javascripts/application.min.js.gz +0 -0
  19. data/lib/karafka/web/ui/public/stylesheets/application.min.css +61 -48
  20. data/lib/karafka/web/ui/public/stylesheets/application.min.css.br +0 -0
  21. data/lib/karafka/web/ui/public/stylesheets/application.min.css.gz +0 -0
  22. data/lib/karafka/web/ui/public/stylesheets/libs/tailwind.css +0 -6
  23. data/lib/karafka/web/ui/views/consumers/_consumer.erb +30 -39
  24. data/lib/karafka/web/ui/views/jobs/_job.erb +29 -38
  25. data/lib/karafka/web/ui/views/ux/_status_rows.erb +0 -6
  26. data/lib/karafka/web/version.rb +1 -1
  27. data/package-lock.json +3 -3
  28. metadata +7 -39
  29. checksums.yaml.gz.sig +0 -0
  30. data/certs/cert.pem +0 -26
  31. data/lib/karafka/web/ui/views/consumers/_incompatible.erb +0 -13
  32. data/lib/karafka/web/ui/views/shared/exceptions/incompatible_schema.erb +0 -34
  33. data.tar.gz.sig +0 -0
  34. metadata.gz.sig +0 -2
@@ -36,7 +36,7 @@ module Karafka
36
36
  def add(report, offset)
37
37
  super(report)
38
38
  increment_total_counters(report)
39
- update_process_state(report, offset)
39
+ add_state(report, offset)
40
40
  # We always evict after counters updates because we want to use expired (stopped)
41
41
  # data for counters as it was valid previously. This can happen only when web consumer
42
42
  # had a lag and is catching up.
@@ -46,6 +46,19 @@ module Karafka
46
46
  refresh_current_stats
47
47
  end
48
48
 
49
+ # Registers or updates the given process state based on the report
50
+ #
51
+ # @param report [Hash]
52
+ # @param offset [Integer]
53
+ def add_state(report, offset)
54
+ process_id = report[:process][:id]
55
+
56
+ state[:processes][process_id] = {
57
+ dispatched_at: report[:dispatched_at],
58
+ offset: offset
59
+ }
60
+ end
61
+
49
62
  # @return [Array<Hash, Float>] aggregated current stats value and time from which this
50
63
  # aggregation comes from
51
64
  #
@@ -84,19 +97,6 @@ module Karafka
84
97
  end
85
98
  end
86
99
 
87
- # Registers or updates the given process state based on the report
88
- #
89
- # @param report [Hash]
90
- # @param offset [Integer]
91
- def update_process_state(report, offset)
92
- process_id = report[:process][:id]
93
-
94
- state[:processes][process_id] = {
95
- dispatched_at: report[:dispatched_at],
96
- offset: offset
97
- }
98
- end
99
-
100
100
  # Evicts expired processes from the current state
101
101
  # We consider processes dead if they do not report often enough
102
102
  # @note We do not evict based on states (stopped), because we want to report the
@@ -94,8 +94,7 @@ module Karafka
94
94
  ::Rdkafka::RdkafkaError,
95
95
  Errors::Ui::NotFoundError,
96
96
  Errors::Ui::ProOnlyError,
97
- Errors::Ui::ForbiddenError,
98
- Errors::Ui::IncompatibleSchemaError
97
+ Errors::Ui::ForbiddenError
99
98
  ] do |e|
100
99
  @error = true
101
100
 
@@ -106,9 +105,6 @@ module Karafka
106
105
  when Errors::Ui::ForbiddenError
107
106
  response.status = 403
108
107
  view 'shared/exceptions/not_allowed'
109
- when Errors::Ui::IncompatibleSchemaError
110
- response.status = 422
111
- view 'shared/exceptions/incompatible_schema'
112
108
  else
113
109
  response.status = 404
114
110
  view 'shared/exceptions/not_found'
@@ -12,6 +12,8 @@ module Karafka
12
12
  # @param process_id [String] id of the process we are looking for
13
13
  # @return [Process] selected process or error raised
14
14
  # @raise [::Karafka::Web::Errors::Ui::NotFoundError] raised if process not found
15
+ # @note Keep in mind, that this search is looking only within processes with a
16
+ # compatible schema, as it uses `#active` under the hood.
15
17
  def find(state, process_id)
16
18
  found_process = Processes.active(state).find { |process| process.id == process_id }
17
19
  found_process || raise(::Karafka::Web::Errors::Ui::NotFoundError, process_id)
@@ -86,7 +88,7 @@ module Karafka
86
88
  # instance. Any incompatibility will cause reporting of incompatible. That's for the
87
89
  # sake of simplicity as the long term goal for user is anyhow to align those.
88
90
  def schema_compatible?
89
- schema_version == ::Karafka::Web::Tracking::Consumers::Sampler::SCHEMA_VERSION
91
+ self[:schema_version] == ::Karafka::Web::Tracking::Consumers::Sampler::SCHEMA_VERSION
90
92
  end
91
93
  end
92
94
  end
@@ -11,22 +11,30 @@ module Karafka
11
11
  class << self
12
12
  include ::Karafka::Core::Helpers::Time
13
13
 
14
- # Returns the active processes in an array and alongside of that the current state of
15
- # the system. We use those together in the UI and it would be expensive to pick it up
16
- # while we've already had it.
17
- #
14
+ # Returns processes that are running or recently shutdown. It may also return processes
15
+ # with incompatible schema.
18
16
  # @param state [State] current system state from which we can get processes metadata
19
17
  # @return [Array<Process>]
20
- def active(state)
18
+ def all(state)
21
19
  messages = fetch_reports(state)
22
20
  messages = squash_processes_data(messages)
23
21
  processes = messages.map(&:payload)
24
22
  evict_expired_processes(processes)
25
23
  processes = sort_processes(processes)
26
-
27
24
  processes.map { |process_hash| Process.new(process_hash) }
28
25
  end
29
26
 
27
+ # Returns the active processes in an array and alongside of that the current state of
28
+ # the system. We use those together in the UI and it would be expensive to pick it up
29
+ # while we've already had it. Active means it is running (or recently shutdown) and
30
+ # it has current schema. Basically any process about which we can reason
31
+ #
32
+ # @param state [State] current system state from which we can get processes metadata
33
+ # @return [Array<Process>]
34
+ def active(state)
35
+ all(state).delete_if { |process| !process.schema_compatible? }
36
+ end
37
+
30
38
  private
31
39
 
32
40
  # Fetches the relevant processes reports from the reports topic
@@ -79,6 +87,19 @@ module Karafka
79
87
  end
80
88
  end
81
89
 
90
+ # Removes processes that have schema different than the one supported by the Web UI
91
+ # We support incompatible schema processes reporting in the status page so users know
92
+ # what and how to update. For other processes we do not display them or their data
93
+ # as it would be too complex to support
94
+ #
95
+ # @param processes [Array<Hash>]
96
+ # @return [Array<Hash>] only data about processes running current schema
97
+ def evict_incompatible_processes(processes)
98
+ processes.delete_if do |details|
99
+ details[:schema_version] != Tracking::Consumers::Sampler::SCHEMA_VERSION
100
+ end
101
+ end
102
+
82
103
  # Ensures that we always return processes sorted by their id
83
104
  # @param processes [Array<Hash>]
84
105
  # @return [Array<Hash>] sorted processes data
@@ -183,7 +183,7 @@ module Karafka
183
183
  # @return [Status::Step] could we read and operate on the current processes data (if any)
184
184
  def consumers_reports
185
185
  if initial_consumers_metrics.success?
186
- @processes ||= Models::Processes.active(@current_state)
186
+ @processes ||= Models::Processes.all(@current_state)
187
187
  status = :success
188
188
  else
189
189
  status = :halted
@@ -21,7 +21,6 @@
21
21
  --font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono",
22
22
  "Courier New", monospace;
23
23
  --color-red-500: oklch(63.7% 0.237 25.331);
24
- --color-orange-500: oklch(70.5% 0.213 47.604);
25
24
  --color-blue-500: oklch(62.3% 0.214 259.815);
26
25
  --color-blue-600: oklch(54.6% 0.245 262.881);
27
26
  --color-gray-50: oklch(98.5% 0.002 247.839);
@@ -452,7 +451,7 @@
452
451
  --tab-radius-min: calc(0.75rem - var(--border));
453
452
  border-color: #0000;
454
453
  order: var(--tab-order);
455
- height: calc(var(--size-field, 0.25rem) * 10);
454
+ height: var(--tab-height);
456
455
  font-size: 0.875rem;
457
456
  padding-inline-start: var(--tab-p);
458
457
  padding-inline-end: var(--tab-p);
@@ -475,7 +474,7 @@
475
474
  &:checked, &:is(label:has(:checked)), &:is(.tab-active, [aria-selected="true"]) {
476
475
  & + .tab-content {
477
476
  display: block;
478
- height: 100%;
477
+ height: calc(100% - var(--tab-height) + var(--border));
479
478
  }
480
479
  }
481
480
  &:not(:checked, label:has(:checked), :hover, .tab-active, [aria-selected="true"]) {
@@ -895,7 +894,7 @@
895
894
  --input-color: var(--color-success);
896
895
  }
897
896
  }
898
- &:user-invalid, &:has(:user-invalid), &[aria-invalid] {
897
+ &:user-invalid, &:has(:user-invalid), &[aria-invalid]:not([aria-invalid="false"]) {
899
898
  &, &:focus, &:checked, &[aria-checked="true"], &:focus-within {
900
899
  --input-color: var(--color-error);
901
900
  }
@@ -1114,6 +1113,7 @@
1114
1113
  width: clamp(3rem, 20rem, 100%);
1115
1114
  height: var(--size);
1116
1115
  font-size: 0.875rem;
1116
+ touch-action: manipulation;
1117
1117
  border-start-start-radius: var(--join-ss, var(--radius-field));
1118
1118
  border-start-end-radius: var(--join-se, var(--radius-field));
1119
1119
  border-end-start-radius: var(--join-es, var(--radius-field));
@@ -1147,6 +1147,9 @@
1147
1147
  }
1148
1148
  }
1149
1149
  }
1150
+ :where(input[type="url"]), :where(input[type="email"]) {
1151
+ direction: ltr;
1152
+ }
1150
1153
  :where(input[type="date"]) {
1151
1154
  display: inline-block;
1152
1155
  }
@@ -1729,6 +1732,7 @@
1729
1732
  width: clamp(3rem, 20rem, 100%);
1730
1733
  height: var(--size);
1731
1734
  font-size: 0.875rem;
1735
+ touch-action: manipulation;
1732
1736
  border-start-start-radius: var(--join-ss, var(--radius-field));
1733
1737
  border-start-end-radius: var(--join-se, var(--radius-field));
1734
1738
  border-end-start-radius: var(--join-es, var(--radius-field));
@@ -3084,6 +3088,7 @@
3084
3088
  flex-wrap: wrap;
3085
3089
  --tabs-height: auto;
3086
3090
  --tabs-direction: row;
3091
+ --tab-height: calc(var(--size-field, 0.25rem) * 10);
3087
3092
  height: var(--tabs-height);
3088
3093
  flex-direction: var(--tabs-direction);
3089
3094
  }
@@ -3836,13 +3841,6 @@
3836
3841
  border-left-color: var(--color-error);
3837
3842
  }
3838
3843
  }
3839
- .status-row-incompatible {
3840
- table & td:first-child {
3841
- border-left-style: var(--tw-border-style);
3842
- border-left-width: 1px;
3843
- border-left-color: var(--color-secondary);
3844
- }
3845
- }
3846
3844
  .status-row-quiet {
3847
3845
  table & td:first-child {
3848
3846
  border-left-style: var(--tw-border-style);
@@ -4185,9 +4183,6 @@
4185
4183
  .text-muted {
4186
4184
  color: var(--color-gray-500);
4187
4185
  }
4188
- .text-orange-500 {
4189
- color: var(--color-orange-500);
4190
- }
4191
4186
  .text-red-500 {
4192
4187
  color: var(--color-red-500);
4193
4188
  }
@@ -4224,6 +4219,15 @@
4224
4219
  --btn-fg: currentColor;
4225
4220
  }
4226
4221
  }
4222
+ @media (hover: none) {
4223
+ &:hover:not(.btn-active, :active, :focus-visible, :disabled, [disabled], .btn-disabled) {
4224
+ --btn-shadow: "";
4225
+ --btn-bg: #0000;
4226
+ --btn-border: #0000;
4227
+ --btn-noise: none;
4228
+ --btn-fg: currentColor;
4229
+ }
4230
+ }
4227
4231
  }
4228
4232
  .blur {
4229
4233
  --tw-blur: blur(8px);
@@ -4595,6 +4599,15 @@ tr:not(:first-child) th[colspan]:not([colspan="1"]) {
4595
4599
  --btn-fg: currentColor;
4596
4600
  }
4597
4601
  }
4602
+ @media (hover: none) {
4603
+ &:hover:not(.btn-active, :active, :focus-visible, :disabled, [disabled], .btn-disabled) {
4604
+ --btn-shadow: "";
4605
+ --btn-bg: #0000;
4606
+ --btn-border: #0000;
4607
+ --btn-noise: none;
4608
+ --btn-fg: currentColor;
4609
+ }
4610
+ }
4598
4611
  --fontsize: 0.75rem;
4599
4612
  --btn-p: 0.75rem;
4600
4613
  --size: calc(var(--size-field, 0.25rem) * 8);
@@ -4738,14 +4751,10 @@ tr:not(:first-child) th[colspan]:not([colspan="1"]) {
4738
4751
  }
4739
4752
  }
4740
4753
  @layer base {
4741
- :root:has( .modal-open, .modal[open], .modal:target, .modal-toggle:checked, .drawer:not([class*="drawer-open"]) > .drawer-toggle:checked ) {
4742
- overflow: hidden;
4743
- }
4744
- }
4745
- @layer base {
4746
- :root, [data-theme] {
4747
- background-color: var(--root-bg, var(--color-base-100));
4748
- color: var(--color-base-content);
4754
+ @property --radialprogress {
4755
+ syntax: "<percentage>";
4756
+ inherits: true;
4757
+ initial-value: 0%;
4749
4758
  }
4750
4759
  }
4751
4760
  @layer base {
@@ -4757,10 +4766,16 @@ tr:not(:first-child) th[colspan]:not([colspan="1"]) {
4757
4766
  }
4758
4767
  }
4759
4768
  @layer base {
4760
- @property --radialprogress {
4761
- syntax: "<percentage>";
4762
- inherits: true;
4763
- initial-value: 0%;
4769
+ :root {
4770
+ --fx-noise: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='a'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='1.34' numOctaves='4' stitchTiles='stitch'%3E%3C/feTurbulence%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23a)' opacity='0.2'%3E%3C/rect%3E%3C/svg%3E");
4771
+ }
4772
+ .chat {
4773
+ --mask-chat: url("data:image/svg+xml,%3csvg width='13' height='13' xmlns='http://www.w3.org/2000/svg'%3e%3cpath fill='black' d='M0 11.5004C0 13.0004 2 13.0004 2 13.0004H12H13V0.00036329L12.5 0C12.5 0 11.977 2.09572 11.8581 2.50033C11.6075 3.35237 10.9149 4.22374 9 5.50036C6 7.50036 0 10.0004 0 11.5004Z'/%3e%3c/svg%3e");
4774
+ }
4775
+ }
4776
+ @layer base {
4777
+ :root:has( .modal-open, .modal[open], .modal:target, .modal-toggle:checked, .drawer:not([class*="drawer-open"]) > .drawer-toggle:checked ) {
4778
+ overflow: hidden;
4764
4779
  }
4765
4780
  }
4766
4781
  @layer base {
@@ -4777,16 +4792,25 @@ tr:not(:first-child) th[colspan]:not([colspan="1"]) {
4777
4792
  }
4778
4793
  }
4779
4794
  @layer base {
4780
- :root {
4781
- --fx-noise: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='a'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='1.34' numOctaves='4' stitchTiles='stitch'%3E%3C/feTurbulence%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23a)' opacity='0.2'%3E%3C/rect%3E%3C/svg%3E");
4795
+ :root, [data-theme] {
4796
+ background-color: var(--root-bg, var(--color-base-100));
4797
+ color: var(--color-base-content);
4782
4798
  }
4783
- .chat {
4784
- --mask-chat: url("data:image/svg+xml,%3csvg width='13' height='13' xmlns='http://www.w3.org/2000/svg'%3e%3cpath fill='black' d='M0 11.5004C0 13.0004 2 13.0004 2 13.0004H12H13V0.00036329L12.5 0C12.5 0 11.977 2.09572 11.8581 2.50033C11.6075 3.35237 10.9149 4.22374 9 5.50036C6 7.50036 0 10.0004 0 11.5004Z'/%3e%3c/svg%3e");
4799
+ }
4800
+ @keyframes radio {
4801
+ 0% {
4802
+ padding: 5px;
4803
+ }
4804
+ 50% {
4805
+ padding: 3px;
4785
4806
  }
4786
4807
  }
4787
- @keyframes dropdown {
4808
+ @keyframes skeleton {
4788
4809
  0% {
4789
- opacity: 0;
4810
+ background-position: 150%;
4811
+ }
4812
+ 100% {
4813
+ background-position: -50%;
4790
4814
  }
4791
4815
  }
4792
4816
  @keyframes progress {
@@ -4804,28 +4828,17 @@ tr:not(:first-child) th[colspan]:not([colspan="1"]) {
4804
4828
  opacity: 1;
4805
4829
  }
4806
4830
  }
4831
+ @keyframes dropdown {
4832
+ 0% {
4833
+ opacity: 0;
4834
+ }
4835
+ }
4807
4836
  @keyframes rating {
4808
4837
  0%, 40% {
4809
4838
  scale: 1.1;
4810
4839
  filter: brightness(1.05) contrast(1.05);
4811
4840
  }
4812
4841
  }
4813
- @keyframes radio {
4814
- 0% {
4815
- padding: 5px;
4816
- }
4817
- 50% {
4818
- padding: 3px;
4819
- }
4820
- }
4821
- @keyframes skeleton {
4822
- 0% {
4823
- background-position: 150%;
4824
- }
4825
- 100% {
4826
- background-position: -50%;
4827
- }
4828
- }
4829
4842
  @property --tw-border-style {
4830
4843
  syntax: "*";
4831
4844
  inherits: false;
@@ -507,12 +507,6 @@
507
507
  }
508
508
  }
509
509
 
510
- @utility status-row-incompatible {
511
- table & td:first-child {
512
- @apply border-l border-l-secondary;
513
- }
514
- }
515
-
516
510
  @utility code {
517
511
  @apply text-sm border border-gray-300;
518
512
  }
@@ -1,45 +1,36 @@
1
- <% if process.schema_compatible? %>
2
- <tr class="status-row-<%= process.status %>">
3
- <td>
4
- <p>
5
- <a href="<%= consumer_path(process.id, 'subscriptions') %>">
6
- <%== truncate(process.id, strategy: :middle) %>
7
- </a>
8
- </p>
1
+ <tr class="status-row-<%= process.status %>">
2
+ <td>
3
+ <p>
4
+ <a href="<%= consumer_path(process.id, 'subscriptions') %>">
5
+ <%== truncate(process.id, strategy: :middle) %>
6
+ </a>
7
+ </p>
9
8
 
10
- <p class="mt-1">
11
- <%== partial 'consumers/assignments_badges', locals: { process: process } %>
12
- </p>
9
+ <p class="mt-1">
10
+ <%== partial 'consumers/assignments_badges', locals: { process: process } %>
11
+ </p>
13
12
 
14
- <p>
15
- <%== tags(process.tags) %>
16
- </p>
17
- </td>
13
+ <p>
14
+ <%== tags(process.tags) %>
15
+ </p>
16
+ </td>
18
17
 
19
- <td>
20
- <%== relative_time process.started_at %>
21
- </td>
18
+ <td>
19
+ <%== relative_time process.started_at %>
20
+ </td>
22
21
 
23
- <td>
24
- <%== badge_primary_sm format_memory process.memory_usage %>
25
- </td>
22
+ <td>
23
+ <%== badge_primary_sm format_memory process.memory_usage %>
24
+ </td>
26
25
 
27
- <td>
28
- <span class="badge badge-primary">
29
- <%= process.workers %> /
30
- <%= process.busy %>
31
- </span>
32
- </td>
26
+ <td>
27
+ <span class="badge badge-primary">
28
+ <%= process.workers %> /
29
+ <%= process.busy %>
30
+ </span>
31
+ </td>
33
32
 
34
- <td>
35
- <%= process.lag_hybrid %>
36
- </td>
37
- </tr>
38
- <% else %>
39
- <%==
40
- partial(
41
- 'consumers/incompatible',
42
- locals: { colspan: 5, process: process }
43
- )
44
- %>
45
- <% end %>
33
+ <td>
34
+ <%= process.lag_hybrid %>
35
+ </td>
36
+ </tr>
@@ -1,39 +1,30 @@
1
- <% if job.process.schema_compatible? %>
2
- <tr>
3
- <td>
4
- <a href="<%= consumer_path(job.process.id, 'subscriptions') %>">
5
- <%== truncate(job.process.id, strategy: :middle) %>
6
- </a>
7
- </td>
8
- <td>
9
- <span class="badge badge-secondary" title="Consumer group: <%= job.consumer_group %>">
10
- <%= job.topic %>:
11
- <%= job.partition %>
12
- </span>
13
- </td>
14
- <td>
15
- <code><%= job.consumer %></code>
1
+ <tr>
2
+ <td>
3
+ <a href="<%= consumer_path(job.process.id, 'subscriptions') %>">
4
+ <%== truncate(job.process.id, strategy: :middle) %>
5
+ </a>
6
+ </td>
7
+ <td>
8
+ <span class="badge badge-secondary" title="Consumer group: <%= job.consumer_group %>">
9
+ <%= job.topic %>:
10
+ <%= job.partition %>
11
+ </span>
12
+ </td>
13
+ <td>
14
+ <code><%= job.consumer %></code>
16
15
 
17
- <% unless job.tags.empty? %>
18
- <br/>
19
- <%== tags(job.tags) %>
20
- <% end %>
21
- </td>
22
- <td>
23
- <code>#<%= job.type %></code>
24
- </td>
25
- <td>
26
- <%== offset_with_label job.topic, job.partition, job.first_offset %>
27
- </td>
28
- <td>
29
- <%== relative_time job.updated_at %>
30
- </td>
31
- </tr>
32
- <% else %>
33
- <%==
34
- partial(
35
- 'consumers/incompatible',
36
- locals: { colspan: 5, process: job.process }
37
- )
38
- %>
39
- <% end %>
16
+ <% unless job.tags.empty? %>
17
+ <br/>
18
+ <%== tags(job.tags) %>
19
+ <% end %>
20
+ </td>
21
+ <td>
22
+ <code>#<%= job.type %></code>
23
+ </td>
24
+ <td>
25
+ <%== offset_with_label job.topic, job.partition, job.first_offset %>
26
+ </td>
27
+ <td>
28
+ <%== relative_time job.updated_at %>
29
+ </td>
30
+ </tr>
@@ -58,12 +58,6 @@
58
58
  <td>.status-row-error</td>
59
59
  <td>.status-row-error</td>
60
60
  </tr>
61
-
62
- <tr class="status-row-incompatible">
63
- <td>.status-row-incompatible</td>
64
- <td>.status-row-incompatible</td>
65
- <td>.status-row-incompatible</td>
66
- </tr>
67
61
  </tbody>
68
62
  </table>
69
63
  </div>
@@ -3,6 +3,6 @@
3
3
  module Karafka
4
4
  module Web
5
5
  # Current gem version
6
- VERSION = '0.11.0.beta1'
6
+ VERSION = '0.11.0.beta3'
7
7
  end
8
8
  end
data/package-lock.json CHANGED
@@ -1034,9 +1034,9 @@
1034
1034
  }
1035
1035
  },
1036
1036
  "node_modules/daisyui": {
1037
- "version": "5.0.35",
1038
- "resolved": "https://registry.npmjs.org/daisyui/-/daisyui-5.0.35.tgz",
1039
- "integrity": "sha512-AWi11n/x5++mps55jcwrBf0Lmip1euWY0FYcH/05SFGmoqrU7S7/aIUWaiaeqlJ5EcmEZ/7zEY73aOxMv6hcIg==",
1037
+ "version": "5.0.37",
1038
+ "resolved": "https://registry.npmjs.org/daisyui/-/daisyui-5.0.37.tgz",
1039
+ "integrity": "sha512-PLc+MhWAqTwolygEGPDi+ac+OsFqIt9nZylTIiyVlEx8loYL7Pt7hNWb8cp5pQQ9dhjYnda1ERiuM6OsJmvPGw==",
1040
1040
  "dev": true,
1041
1041
  "license": "MIT",
1042
1042
  "funding": {