Skip to content

Commit 94d576f

Browse files
committed
Implement the reactive messaging card
1 parent 4bee348 commit 94d576f

File tree

4 files changed

+191
-0
lines changed

4 files changed

+191
-0
lines changed

extensions/smallrye-reactive-messaging/deployment/pom.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,11 @@
4242
<groupId>org.commonmark</groupId>
4343
<artifactId>commonmark</artifactId>
4444
</dependency>
45+
<dependency>
46+
<groupId>io.quarkus</groupId>
47+
<artifactId>quarkus-vertx-http-dev-ui-spi</artifactId>
48+
</dependency>
49+
4550
<dependency>
4651
<groupId>io.quarkus</groupId>
4752
<artifactId>quarkus-vertx-http-deployment</artifactId>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package io.quarkus.smallrye.reactivemessaging.deployment.devconsole;
2+
3+
import io.quarkus.deployment.IsDevelopment;
4+
import io.quarkus.deployment.annotations.BuildStep;
5+
import io.quarkus.devui.spi.JsonRPCProvidersBuildItem;
6+
import io.quarkus.devui.spi.page.CardPageBuildItem;
7+
import io.quarkus.devui.spi.page.Page;
8+
import io.quarkus.smallrye.reactivemessaging.runtime.devconsole.ReactiveMessagingJsonRpcService;
9+
10+
public class ReactiveMessagingDevUiProcessor {
11+
12+
@BuildStep(onlyIf = IsDevelopment.class)
13+
CardPageBuildItem create() {
14+
CardPageBuildItem card = new CardPageBuildItem("SmallRye Reactive Messaging");
15+
card.addPage(Page.webComponentPageBuilder()
16+
.title("Channels")
17+
.componentLink("qwc-smallrye-reactive-messaging-channels.js")
18+
.icon("font-awesome-solid:diagram-project"));
19+
20+
return card;
21+
}
22+
23+
@BuildStep(onlyIf = IsDevelopment.class)
24+
JsonRPCProvidersBuildItem createJsonRPCServiceForCache() {
25+
return new JsonRPCProvidersBuildItem("SmallRyeReactiveMessaging",
26+
ReactiveMessagingJsonRpcService.class);
27+
}
28+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
import { LitElement, html} from 'lit';
2+
import { JsonRpc } from 'jsonrpc';
3+
import '@vaadin/icon';
4+
import '@vaadin/button';
5+
import { until } from 'lit/directives/until.js';
6+
import '@vaadin/grid';
7+
import { columnBodyRenderer } from '@vaadin/grid/lit.js';
8+
import '@vaadin/grid/vaadin-grid-sort-column.js';
9+
import { unsafeHTML } from 'lit-html/directives/unsafe-html.js';
10+
11+
12+
export class QwcSmallryeReactiveMessagingChannels extends LitElement {
13+
14+
jsonRpc = new JsonRpc("SmallRyeReactiveMessaging");
15+
16+
static properties = {
17+
"_channels": {state: true, type: Array}
18+
}
19+
20+
/**
21+
* Called when displayed
22+
*/
23+
connectedCallback() {
24+
super.connectedCallback();
25+
this.jsonRpc.getInfo().then(jsonRpcResponse => {
26+
this._channels = [];
27+
jsonRpcResponse.result.forEach(c => {
28+
this._channels.push(c);
29+
});
30+
});
31+
}
32+
33+
/**
34+
* Called when it needs to render the components
35+
* @returns {*}
36+
*/
37+
render() {
38+
return html`${until(this._renderChannelTable(), html`<span>Loading channels...</span>`)}`;
39+
}
40+
41+
_renderChannelTable() {
42+
if (this._channels) {
43+
return html`
44+
<vaadin-grid .items="${this._channels}" class="datatable" theme="no-border">
45+
<vaadin-grid-column auto-width
46+
header="Channel"
47+
${columnBodyRenderer(this._channelNameRenderer, [])}>
48+
</vaadin-grid-column>
49+
50+
<vaadin-grid-column auto-width
51+
header="Publisher"
52+
${columnBodyRenderer(this._channelPublisherRenderer, [])}>>
53+
</vaadin-grid-column>
54+
55+
<vaadin-grid-column auto-width
56+
header="Subscriber(s)"
57+
${columnBodyRenderer(this._channelSubscriberRenderer, [])}
58+
resizable>
59+
</vaadin-grid-column>
60+
</vaadin-grid>`;
61+
}
62+
}
63+
64+
_channelNameRenderer(channel) {
65+
return html`<strong>${ channel.name }</strong>`
66+
}
67+
68+
_channelSubscriberRenderer(channel) {
69+
const consumers = channel.consumers;
70+
if (consumers) {
71+
if (consumers.length === 1) {
72+
return this._renderComponent(consumers[0]);
73+
} else if (consumers.length > 1) {
74+
return html`
75+
<ul>
76+
${consumers.map(item => html`<li>${this._renderComponent(item)}</li>`)}
77+
</ul>
78+
`;
79+
} else {
80+
return html`<em>No subscribers</em>`
81+
}
82+
}
83+
}
84+
85+
_channelPublisherRenderer(channel) {
86+
const publisher = channel.publisher;
87+
if (publisher) {
88+
return this._renderComponent(publisher);
89+
}
90+
}
91+
92+
_renderComponent(component) {
93+
switch (component.type) {
94+
case "PUBLISHER":
95+
return html`<vaadin-icon icon="font-awesome-solid:right-from-bracket" title="publisher"></vaadin-icon> ${unsafeHTML(component.description)}`
96+
case "SUBSCRIBER":
97+
return html`<vaadin-icon icon="font-awesome-solid:right-to-bracket" title="subscriber"></vaadin-icon> ${unsafeHTML(component.description)}`
98+
case "PROCESSOR":
99+
return html`<vaadin-icon icon="font-awesome-solid:arrows-turn-to-dots" title="processor" />"></vaadin-icon> ${unsafeHTML(component.description)}`
100+
case "CONNECTOR":
101+
return html`<vaadin-icon icon="font-awesome-solid:plug" title="connector"></vaadin-icon> ${unsafeHTML(component.description)}`
102+
case "EMITTER":
103+
return html`<vaadin-icon icon="font-awesome-solid:syringe" title="emitter"></vaadin-icon> ${unsafeHTML(component.description)}`
104+
case "CHANNEL":
105+
return html`<vaadin-icon icon="font-awesome-solid:syringe" title="channel"></vaadin-icon> ${unsafeHTML(component.description)}`
106+
}
107+
}
108+
}
109+
customElements.define('qwc-smallrye-reactive-messaging-channels', QwcSmallryeReactiveMessagingChannels);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
package io.quarkus.smallrye.reactivemessaging.runtime.devconsole;
2+
3+
import java.util.List;
4+
5+
import jakarta.enterprise.context.ApplicationScoped;
6+
7+
import io.vertx.core.json.JsonArray;
8+
import io.vertx.core.json.JsonObject;
9+
10+
@ApplicationScoped
11+
public class ReactiveMessagingJsonRpcService {
12+
13+
// IMPORTANT: To avoid having to depend on jackson, we build a JSON array containing the description of the channels.
14+
15+
public JsonArray getInfo() {
16+
JsonArray result = new JsonArray();
17+
18+
List<DevReactiveMessagingInfos.DevChannelInfo> channels = new DevReactiveMessagingInfos().getChannels();
19+
for (DevReactiveMessagingInfos.DevChannelInfo channel : channels) {
20+
JsonObject channelAsJson = toJson(channel);
21+
result.add(channelAsJson);
22+
}
23+
return result;
24+
}
25+
26+
private JsonObject toJson(DevReactiveMessagingInfos.DevChannelInfo channel) {
27+
JsonObject json = new JsonObject();
28+
json.put("name", channel.getName());
29+
json.put("publisher", toJson(channel.getPublisher()));
30+
json.put("consumers", toJson(channel.getConsumers()));
31+
return json;
32+
}
33+
34+
private JsonArray toJson(List<DevReactiveMessagingInfos.Component> components) {
35+
JsonArray array = new JsonArray();
36+
for (DevReactiveMessagingInfos.Component component : components) {
37+
array.add(toJson(component));
38+
}
39+
return array;
40+
}
41+
42+
private JsonObject toJson(DevReactiveMessagingInfos.Component component) {
43+
JsonObject json = new JsonObject();
44+
json.put("type", component.type.toString());
45+
json.put("description", component.description);
46+
json.put("isConnector", component.isConnector());
47+
return json;
48+
}
49+
}

0 commit comments

Comments
 (0)