Skip to content

Commit 1535b3b

Browse files
authored
Merge pull request #2 from veepee-oss/refactor-components
Refactor components
2 parents dc05cc8 + 0ef3445 commit 1535b3b

24 files changed

+992
-807
lines changed

Components/Brokers.razor

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
<div class="form-group row">
2+
<label for="brokers" class="col-2 col-form-label text-right">Brokers</label>
3+
<div class="col-10">
4+
<div class="input-group">
5+
<input type="text" class="form-control" id="brokers" placeholder="host" @bind="Options.KafkaConfig.CurrentSetting.Brokers">
6+
<div class="input-group-append">
7+
<button class="btn btn-outline-secondary" type="button" data-toggle="modal" data-target="#brokerOptionsModal"><span class="oi oi-wrench"></span></button>
8+
<button class="btn btn-outline-secondary @(Options.KafkaConfig.CurrentSetting.IsSaslActivated ? " btn-primary" : string.Empty)" type="button" data-toggle="modal" data-target="#brokerSecurityModal"><span class="oi oi-lock-unlocked"></span></button>
9+
</div>
10+
</div>
11+
</div>
12+
</div>
13+
14+
<div class="modal fade" id="brokerOptionsModal" tabindex="-1" role="dialog">
15+
<div class="modal-dialog modal-lg modal-dialog-centered" role="document">
16+
<div class="modal-content">
17+
<div class="modal-header">
18+
<h5 class="modal-title">Options</h5>
19+
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
20+
<span aria-hidden="true">&times;</span>
21+
</button>
22+
</div>
23+
<div class="modal-body">
24+
<form>
25+
<div class="form-group">
26+
<div class="form-check">
27+
<input class="form-check-input" type="checkbox" id="isGzipActivated" @bind="Options.KafkaConfig.CurrentSetting.IsGzipActivated">
28+
<label class="form-check-label" for="isGzipActivated">Try activate GZIP decompression (can take more time to process)</label>
29+
</div>
30+
</div>
31+
</form>
32+
</div>
33+
<div class="modal-footer">
34+
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
35+
</div>
36+
</div>
37+
</div>
38+
</div>
39+
40+
<div class="modal fade" id="brokerSecurityModal" tabindex="-1" role="dialog">
41+
<div class="modal-dialog modal-lg modal-dialog-centered" role="document">
42+
<div class="modal-content">
43+
<div class="modal-header">
44+
<h5 class="modal-title">Security</h5>
45+
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
46+
<span aria-hidden="true">&times;</span>
47+
</button>
48+
</div>
49+
<div class="modal-body">
50+
<form>
51+
<div class="form-group">
52+
<div class="form-check">
53+
<input class="form-check-input" type="checkbox" id="isSaslActivated" @bind="Options.KafkaConfig.CurrentSetting.IsSaslActivated">
54+
<label class="form-check-label" for="isSaslActivated">Activate SASL</label>
55+
</div>
56+
</div>
57+
<div class="form-row">
58+
<div class="form-group col-6">
59+
<label for="securityProtocol">Security protocol</label>
60+
<select class="form-control" id="securityProtocol" @bind="Options.KafkaConfig.CurrentSetting.SecurityProtocol" disabled="@(!Options.KafkaConfig.CurrentSetting.IsSaslActivated)">
61+
@foreach (var protocol in Enum.GetValues<Confluent.Kafka.SecurityProtocol>())
62+
{
63+
<option value="@protocol">@protocol</option>
64+
}
65+
</select>
66+
</div>
67+
<div class="form-group col-6">
68+
<label for="saslMechanism">SASL mechanism</label>
69+
<select class="form-control" id="saslMechanism" @bind="Options.KafkaConfig.CurrentSetting.SaslMechanism" disabled="@(!Options.KafkaConfig.CurrentSetting.IsSaslActivated)">
70+
@foreach (var mechanism in Enum.GetValues<Confluent.Kafka.SaslMechanism>())
71+
{
72+
<option value="@mechanism">@mechanism</option>
73+
}
74+
</select>
75+
</div>
76+
</div>
77+
<div class="form-group">
78+
<label for="saslUserName">Username</label>
79+
<input type="text" class="form-control" id="saslUserName" placeholder="username" @bind="Options.KafkaConfig.CurrentSetting.SaslUsername" disabled="@(!Options.KafkaConfig.CurrentSetting.IsSaslActivated)">
80+
</div>
81+
<div class="form-group">
82+
<label for="saslPassword">Password</label>
83+
<input type="password" class="form-control" id="saslPassword" placeholder="password" @bind="Options.KafkaConfig.CurrentSetting.SaslPassword" disabled="@(!Options.KafkaConfig.CurrentSetting.IsSaslActivated)">
84+
</div>
85+
</form>
86+
</div>
87+
<div class="modal-footer">
88+
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
89+
</div>
90+
</div>
91+
</div>
92+
</div>

Components/Brokers.razor.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
using KafkaTester.Model;
2+
using Microsoft.AspNetCore.Components;
3+
4+
namespace KafkaTester.Components;
5+
6+
public partial class Brokers
7+
{
8+
[Parameter]
9+
public Options Options { get; set; }
10+
}

Components/Filter.razor

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
<div class="form-group row">
2+
<label for="filter" class="col-2 col-form-label text-right">Filter</label>
3+
<div class="col-10">
4+
<div class="input-group">
5+
<input type="text" class="form-control" id="filter" @bind="Options.Filter.Text" @bind:event="oninput" @onkeyup="OnFilterChange">
6+
<div class="input-group-append">
7+
<button class="btn btn-outline-secondary" type="button" data-toggle="modal" data-target="#searchSettings"><span class="oi oi-cog"></span></button>
8+
</div>
9+
</div>
10+
</div>
11+
</div>
12+
13+
<div class="modal fade" id="searchSettings" tabindex="-1" role="dialog">
14+
<div class="modal-dialog modal-lg modal-dialog-centered" role="document">
15+
<div class="modal-content">
16+
<div class="modal-header">
17+
<h5 class="modal-title">Settings</h5>
18+
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
19+
<span aria-hidden="true">&times;</span>
20+
</button>
21+
</div>
22+
<div class="modal-body">
23+
<form>
24+
<div class="form-group">
25+
<div class="form-check">
26+
<input class="form-check-input" type="checkbox" id="isInvariantCase" @bind="Options.Filter.IsInvariantCase">
27+
<label class="form-check-label" for="isInvariantCase">Invariant case (can take more time)</label>
28+
</div>
29+
<div class="form-check">
30+
<input class="form-check-input" type="checkbox" id="hasCheckKey" @bind="Options.Filter.IsCheckKey">
31+
<label class="form-check-label" for="hasCheckKey">Search in the key</label>
32+
</div>
33+
<div class="form-check">
34+
<input class="form-check-input" type="checkbox" id="hasCheckMessage" @bind="Options.Filter.IsCheckMessage">
35+
<label class="form-check-label" for="hasCheckMessage">Search in the message</label>
36+
</div>
37+
</div>
38+
</form>
39+
</div>
40+
</div>
41+
</div>
42+
</div>

Components/Filter.razor.cs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
using KafkaTester.Model;
2+
using Microsoft.AspNetCore.Components;
3+
4+
namespace KafkaTester.Components;
5+
6+
public partial class Filter
7+
{
8+
private string _oldFilterValue;
9+
10+
[Parameter]
11+
public Options Options { get; set; }
12+
13+
[Parameter]
14+
public EventCallback<FilterSettings> OnChanged { get; set; }
15+
16+
private void OnFilterChange()
17+
{
18+
if (_oldFilterValue == Options.Filter.Text)
19+
return;
20+
_oldFilterValue = Options.Filter.Text;
21+
OnChanged.InvokeAsync();
22+
}
23+
}

Components/Messages.razor

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
<div class="spinner @(Options.IsSearching ? "visible" : "invisible")">
2+
<div class="rect1"></div>
3+
<div class="rect2"></div>
4+
<div class="rect3"></div>
5+
<div class="rect4"></div>
6+
<div class="rect5"></div>
7+
</div>
8+
@if (Items.Any() || Options.IsSearching)
9+
{
10+
<table class="table">
11+
<thead>
12+
<tr>
13+
<th class="col-2">Offset (Partition)</th>
14+
<th class="col-2">Date & Time</th>
15+
<th class="col">Message (@(Options.Filter.IsFiltering() ? $"{Items.Count} item(s) / {CountTotalMessages} item(s)" : $"{CountTotalMessages} item(s)"))</th>
16+
</tr>
17+
</thead>
18+
<tbody>
19+
<Virtualize Context="message" Items="@Items">
20+
<tr>
21+
<td class="offset">@message.Offset (@message.Partition)</td>
22+
<td class="datetime">@message.MessageDateTime</td>
23+
<td class="message" nowrap>
24+
<button class="btn btn-light d-inline" @onclick="() => ShowSelectedMessage(message)"><span class="oi oi-eye"></span></button>
25+
<div class="d-inline">
26+
@if (message.Key is not null)
27+
{
28+
<small>Key: @message.Key</small>
29+
}
30+
@message.Message.Substring(0, Math.Min(message.Message.Length, 250))
31+
</div>
32+
</td>
33+
</tr>
34+
</Virtualize>
35+
</tbody>
36+
</table>
37+
}
38+
else
39+
{
40+
<div class="text-center">No content</div>
41+
}
42+
<pre class="text-danger">
43+
@foreach (var error in Errors)
44+
{
45+
@(error + "\n")
46+
}
47+
</pre>
48+
49+
@if(SelectedMessage is not null)
50+
{
51+
<div class="modal fade" id="seeMessageModal" tabindex="-1" role="dialog">
52+
<div class="modal-dialog modal-lg modal-dialog-centered" role="document">
53+
<div class="modal-content">
54+
<div class="modal-header">
55+
<h5 class="modal-title">Message</h5>
56+
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
57+
<span aria-hidden="true">&times;</span>
58+
</button>
59+
</div>
60+
@if (SelectedMessage.Key is not null)
61+
{
62+
<div class="modal-header">
63+
<div class="font-weight-bold">@SelectedMessage.Key</div>
64+
</div>
65+
}
66+
<div class="modal-body">
67+
<pre>
68+
<code class="@(IsValidJson(SelectedMessage.Message) ? "language-json" : "nohighlight")">
69+
@SelectedMessage.Message
70+
</code>
71+
</pre>
72+
</div>
73+
<div class="modal-subbody">
74+
<div class="headers">
75+
@if (SelectedMessage.Headers.Any())
76+
{
77+
<div class="collapse" id="collapseExample">
78+
<div class="card card-body">
79+
<div class="row font-weight-bold">
80+
<div class="col">Key</div>
81+
<div class="col">Value</div>
82+
</div>
83+
@foreach (var header in SelectedMessage.Headers)
84+
{
85+
<div class="row">
86+
<div class="col">@header.Key</div>
87+
<div class="col">@header.Value</div>
88+
</div>
89+
}
90+
</div>
91+
</div>
92+
}
93+
</div>
94+
</div>
95+
<div class="modal-footer justify-content-between">
96+
@if (SelectedMessage.Headers.Any())
97+
{
98+
<a class="btn-header btn btn-outline-dark collapsed" data-toggle="collapse" href="#collapseExample" role="button" aria-expanded="false" aria-controls="collapseExample">
99+
<i class="oi oi-caret-top pull-right"></i> @SelectedMessage.Headers.Count Header(s)
100+
</a>
101+
}
102+
else
103+
{
104+
<div class="font-italic">No header</div>
105+
}
106+
<div>
107+
<button type="button" class="btn btn-light" @onclick="() => CopyMessage(JsonPrettify(SelectedMessage.Message))">Copy</button>
108+
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
109+
</div>
110+
</div>
111+
</div>
112+
}
113+
</div>
114+
</div>
115+
}

Components/Messages.razor.cs

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
using KafkaTester.Model;
2+
using KafkaTester.Service;
3+
using Microsoft.AspNetCore.Components;
4+
using Microsoft.JSInterop;
5+
using System.Collections.Generic;
6+
using System.Text.Json;
7+
using System.Threading.Tasks;
8+
9+
namespace KafkaTester.Components;
10+
11+
public partial class Messages
12+
{
13+
[Inject] private IJSRuntime JsRuntime { get; set; }
14+
15+
[Parameter]
16+
public ICollection<KafkaMessage> Items { get; set; }
17+
18+
[Parameter]
19+
public List<string> Errors { get; set; }
20+
21+
[Parameter]
22+
public KafkaMessage SelectedMessage { get; set; }
23+
24+
[Parameter]
25+
public Options Options { get; set; }
26+
27+
[Parameter]
28+
public int CountTotalMessages { get; set; }
29+
30+
private async Task ShowSelectedMessage(KafkaMessage message)
31+
{
32+
SelectedMessage = message;
33+
await JsRuntime.InvokeVoidAsync("openSeeMessageModal", JsonPrettify(SelectedMessage.Message));
34+
}
35+
36+
private string JsonPrettify(string json)
37+
{
38+
System.Diagnostics.Trace.WriteLine(json);
39+
if (IsValidJson(json))
40+
return JsonSerializer.Serialize(JsonDocument.Parse(json), new JsonSerializerOptions { WriteIndented = true });
41+
else
42+
return json;
43+
}
44+
45+
private bool IsValidJson(string source)
46+
{
47+
if (source == null)
48+
return false;
49+
50+
try
51+
{
52+
JsonDocument.Parse(source);
53+
return true;
54+
}
55+
catch (JsonException)
56+
{
57+
return false;
58+
}
59+
}
60+
61+
private void CopyMessage(string message)
62+
{
63+
JsRuntime.InvokeVoidAsync("clipboardCopy.copyText", message).ConfigureAwait(true);
64+
}
65+
}

Components/Messages.razor.css

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
.table {
2+
max-width: 100%;
3+
}
4+
5+
.table > tbody > tr > td.message {
6+
white-space: nowrap;
7+
overflow: hidden;
8+
text-overflow: ellipsis;
9+
max-width: 0;
10+
}
11+
12+
.table > tbody > tr > td small {
13+
position: absolute;
14+
margin: -10px 0;
15+
opacity: 0.6;
16+
}
17+
.btn-header .oi {
18+
transition: .3s transform ease-in-out;
19+
}
20+
21+
.btn-header.collapsed .oi {
22+
transform: rotate(90deg)
23+
}

0 commit comments

Comments
 (0)