Skip to content

Commit 8f59da1

Browse files
committed
Kafka Streams Dev UI migration to v2
1 parent 58bc0c4 commit 8f59da1

File tree

7 files changed

+682
-0
lines changed

7 files changed

+682
-0
lines changed

build-parent/pom.xml

+104
Original file line numberDiff line numberDiff line change
@@ -487,6 +487,110 @@
487487
<scope>runtime</scope>
488488
</dependency>
489489

490+
<!-- hpcc-js Wasm / Graphviz and dependencies -->
491+
<dependency>
492+
<groupId>org.mvnpm.at.hpcc-js</groupId>
493+
<artifactId>wasm</artifactId>
494+
<version>2.14.1</version>
495+
<scope>runtime</scope>
496+
</dependency>
497+
<dependency>
498+
<groupId>org.mvnpm</groupId>
499+
<artifactId>yargs</artifactId>
500+
<version>17.7.2</version>
501+
<scope>runtime</scope>
502+
</dependency>
503+
<dependency>
504+
<groupId>org.mvnpm</groupId>
505+
<artifactId>cliui</artifactId>
506+
<version>8.0.1</version>
507+
<scope>runtime</scope>
508+
</dependency>
509+
<dependency>
510+
<groupId>org.mvnpm</groupId>
511+
<artifactId>escalade</artifactId>
512+
<version>3.1.1</version>
513+
<scope>runtime</scope>
514+
</dependency>
515+
<dependency>
516+
<groupId>org.mvnpm</groupId>
517+
<artifactId>get-caller-file</artifactId>
518+
<version>2.0.5</version>
519+
<scope>runtime</scope>
520+
</dependency>
521+
<dependency>
522+
<groupId>org.mvnpm</groupId>
523+
<artifactId>require-directory</artifactId>
524+
<version>2.1.1</version>
525+
<scope>runtime</scope>
526+
</dependency>
527+
<dependency>
528+
<groupId>org.mvnpm</groupId>
529+
<artifactId>string-width</artifactId>
530+
<version>4.2.3</version>
531+
<scope>runtime</scope>
532+
</dependency>
533+
<dependency>
534+
<groupId>org.mvnpm</groupId>
535+
<artifactId>y18n</artifactId>
536+
<version>5.0.8</version>
537+
<scope>runtime</scope>
538+
</dependency>
539+
<dependency>
540+
<groupId>org.mvnpm</groupId>
541+
<artifactId>yargs-parser</artifactId>
542+
<version>21.1.1</version>
543+
<scope>runtime</scope>
544+
</dependency>
545+
<dependency>
546+
<groupId>org.mvnpm</groupId>
547+
<artifactId>strip-ansi</artifactId>
548+
<version>6.0.1</version>
549+
<scope>runtime</scope>
550+
</dependency>
551+
<dependency>
552+
<groupId>org.mvnpm</groupId>
553+
<artifactId>wrap-ansi</artifactId>
554+
<version>7.0.0</version>
555+
<scope>runtime</scope>
556+
</dependency>
557+
<dependency>
558+
<groupId>org.mvnpm</groupId>
559+
<artifactId>emoji-regex</artifactId>
560+
<version>8.0.0</version>
561+
<scope>runtime</scope>
562+
</dependency>
563+
<dependency>
564+
<groupId>org.mvnpm</groupId>
565+
<artifactId>is-fullwidth-code-point</artifactId>
566+
<version>3.0.0</version>
567+
<scope>runtime</scope>
568+
</dependency>
569+
<dependency>
570+
<groupId>org.mvnpm</groupId>
571+
<artifactId>ansi-regex</artifactId>
572+
<version>5.0.1</version>
573+
<scope>runtime</scope>
574+
</dependency>
575+
<dependency>
576+
<groupId>org.mvnpm</groupId>
577+
<artifactId>ansi-styles</artifactId>
578+
<version>4.3.0</version>
579+
<scope>runtime</scope>
580+
</dependency>
581+
<dependency>
582+
<groupId>org.mvnpm</groupId>
583+
<artifactId>color-convert</artifactId>
584+
<version>2.0.1</version>
585+
<scope>runtime</scope>
586+
</dependency>
587+
<dependency>
588+
<groupId>org.mvnpm</groupId>
589+
<artifactId>color-name</artifactId>
590+
<version>1.1.4</version>
591+
<scope>runtime</scope>
592+
</dependency>
593+
490594
<!-- Code editor -->
491595
<dependency>
492596
<groupId>org.mvnpm.at.vanillawc</groupId>

extensions/kafka-streams/deployment/pom.xml

+4
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,10 @@
3333
<groupId>io.quarkus</groupId>
3434
<artifactId>quarkus-smallrye-health-spi</artifactId>
3535
</dependency>
36+
<dependency>
37+
<groupId>org.mvnpm.at.hpcc-js</groupId>
38+
<artifactId>wasm</artifactId>
39+
</dependency>
3640

3741
<!-- test dependencies -->
3842
<dependency>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package io.quarkus.kafka.streams.deployment.devui;
2+
3+
import io.quarkus.deployment.IsDevelopment;
4+
import io.quarkus.deployment.annotations.BuildProducer;
5+
import io.quarkus.deployment.annotations.BuildStep;
6+
import io.quarkus.devui.spi.JsonRPCProvidersBuildItem;
7+
import io.quarkus.devui.spi.page.CardPageBuildItem;
8+
import io.quarkus.devui.spi.page.Page;
9+
import io.quarkus.kafka.streams.runtime.devui.KafkaStreamsJsonRPCService;
10+
11+
public class KafkaStreamsDevUIProcessor {
12+
13+
@BuildStep(onlyIf = IsDevelopment.class)
14+
public void createPages(BuildProducer<CardPageBuildItem> cardPageProducer) {
15+
16+
CardPageBuildItem cardPageBuildItem = new CardPageBuildItem();
17+
18+
cardPageBuildItem.addPage(Page.webComponentPageBuilder()
19+
.componentLink("qwc-kafka-streams-topology.js")
20+
.title("Topology")
21+
.icon("font-awesome-solid:diagram-project"));
22+
23+
cardPageProducer.produce(cardPageBuildItem);
24+
}
25+
26+
@BuildStep(onlyIf = IsDevelopment.class)
27+
public void createJsonRPCService(BuildProducer<JsonRPCProvidersBuildItem> jsonRPCServiceProducer) {
28+
jsonRPCServiceProducer.produce(new JsonRPCProvidersBuildItem(KafkaStreamsJsonRPCService.class));
29+
}
30+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
import { QwcHotReloadElement, html, css } from 'qwc-hot-reload-element';
2+
import { unsafeHTML } from 'lit/directives/unsafe-html.js';
3+
import { JsonRpc } from 'jsonrpc';
4+
5+
import { Graphviz } from "@hpcc-js/wasm/graphviz.js";
6+
7+
import '@vaadin/details';
8+
import '@vaadin/tabs';
9+
import '@vaadin/vertical-layout';
10+
import 'qui-badge';
11+
import 'qui-code-block';
12+
13+
/**
14+
* This component shows the Kafka Streams Topology
15+
*/
16+
export class QwcKafkaStreamsTopology extends QwcHotReloadElement {
17+
18+
jsonRpc = new JsonRpc(this);
19+
20+
static styles = css`
21+
.codeBlock {
22+
width: 100%;
23+
height: auto;
24+
}
25+
`;
26+
27+
static properties = {
28+
_topology: {state: true},
29+
_graphviz: {state: true},
30+
_tabContent: {state: true}
31+
};
32+
33+
constructor() {
34+
super();
35+
this._topology = null;
36+
this._graphviz = null;
37+
this._tabContent = '';
38+
}
39+
40+
connectedCallback() {
41+
super.connectedCallback();
42+
Graphviz.load().then(r => this._graphviz = r);
43+
this.hotReload()
44+
}
45+
46+
render() {
47+
if (this._topology) {
48+
return html`<vaadin-tabs @selected-changed="${(e) => this._tabSelectedChanged(e.detail.value)}">
49+
<vaadin-tab id="graphTab">Graph</vaadin-tab>
50+
<vaadin-tab id="detailsTab">Details</vaadin-tab>
51+
<vaadin-tab id="describeTab">Describe</vaadin-tab>
52+
<vaadin-tab id="graphvizTab">Graphviz</vaadin-tab>
53+
<vaadin-tab id="mermaidTab">Mermaid</vaadin-tab>
54+
</vaadin-tabs>
55+
<vaadin-vertical-layout theme="padding"><p>${this._tabContent}</p></vaadin-vertical-layout>`;
56+
}
57+
58+
return html`<qwc-no-data message="You do not have any Topology."
59+
link="https://quarkus.io/guides/kafka-streams"
60+
linkText="Learn how to write Kafka Streams">
61+
</qwc-no-data>`;
62+
}
63+
64+
hotReload() {
65+
this._topology = null;
66+
this.jsonRpc.getTopology().then(jsonRpcResponse => {
67+
this._topology = jsonRpcResponse.result;
68+
});
69+
}
70+
71+
_tabSelectedChanged(n) {
72+
switch(n) {
73+
case 1 : this._selectDetailsTab(); break;
74+
case 2 : this._selectDescribeTab(); break;
75+
case 3 : this._selectGraphvizTab(); break;
76+
case 4 : this._selectMermaidTab(); break;
77+
default : this._selectGraphTab();
78+
}
79+
}
80+
81+
_selectGraphTab() {
82+
if (this._graphviz) {
83+
let g = this._graphviz.dot(this._topology.graphviz);
84+
this._tabContent = html`${unsafeHTML(g)}`;
85+
} else {
86+
this._tabContent = html`Graph engine not started.`;
87+
}
88+
}
89+
90+
_selectDetailsTab() {
91+
this._tabContent = html`<table>
92+
<tr>
93+
<td>Sub-topologies</td><td><qui-badge>${this._topology.subTopologies.length}</qui-badge></td>
94+
<td>${this._topology.subTopologies.map((subTopology) => html`<qui-badge level="contrast" icon="font-awesome-solid:diagram-project" style="margin-right:5px">${subTopology}</qui-badge>`)}</td>
95+
</tr>
96+
<tr>
97+
<td>Sources</td><td><qui-badge>${this._topology.sources.length}</qui-badge></td>
98+
<td>${this._topology.sources.map((source) => html`<qui-badge level="contrast" icon="font-awesome-solid:right-to-bracket" style="margin-right:5px">${source}</qui-badge>`)}</td>
99+
</tr>
100+
<tr>
101+
<td>Sinks</td><td><qui-badge>${this._topology.sinks.length}</qui-badge></td>
102+
<td>${this._topology.sinks.map((sink) => html`<qui-badge level="contrast" icon="font-awesome-solid:right-from-bracket" style="margin-right:5px">${sink}</qui-badge>`)}</td>
103+
</tr>
104+
<tr>
105+
<td>Stores</td><td><qui-badge>${this._topology.stores.length}</qui-badge></td>
106+
<td>${this._topology.stores.map((store) => html`<qui-badge level="contrast" icon="font-awesome-solid:database" style="margin-right:5px">${store}</qui-badge>`)}</td>
107+
</tr>
108+
</table>`;
109+
}
110+
111+
_selectDescribeTab() {
112+
this._tabContent = html`<qui-code-block mode='text' content='${this._topology.describe}' class="codeBlock"></qui-code-block>`;
113+
}
114+
115+
_selectGraphvizTab() {
116+
this._tabContent = html`<qui-code-block mode='gv' content='${this._topology.graphviz}' class="codeBlock"></qui-code-block>`;
117+
}
118+
119+
_selectMermaidTab() {
120+
this._tabContent = html`<qui-code-block mode='mermaid' content='${this._topology.mermaid}' class="codeBlock"></qui-code-block>`;
121+
}
122+
}
123+
customElements.define('qwc-kafka-streams-topology', QwcKafkaStreamsTopology);

0 commit comments

Comments
 (0)