Skip to content

Commit 4326a72

Browse files
Dev UI: new feature - menu actions
Signed-off-by: Phillip Kruger <[email protected]>
1 parent 91ff3e7 commit 4326a72

File tree

14 files changed

+328
-99
lines changed

14 files changed

+328
-99
lines changed

bom/dev-ui/pom.xml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
<path-to-regexp.version>2.4.0</path-to-regexp.version>
3333
<codeblock.version>1.1.1</codeblock.version>
3434
<qomponent.version>1.0.4</qomponent.version>
35+
<ldrs.version>1.1.7</ldrs.version>
3536
<directory-tree.version>1.0.3</directory-tree.version>
3637
<hpcc-js-wasm.version>2.15.3</hpcc-js-wasm.version>
3738
<yargs.version>17.7.2</yargs.version>
@@ -328,6 +329,14 @@
328329
<scope>runtime</scope>
329330
</dependency>
330331

332+
<!-- Loading indicators -->
333+
<dependency>
334+
<groupId>org.mvnpm</groupId>
335+
<artifactId>ldrs</artifactId>
336+
<version>${ldrs.version}</version>
337+
<scope>runtime</scope>
338+
</dependency>
339+
331340
<!-- Polyfill for importmaps -->
332341
<dependency>
333342
<groupId>org.mvnpm</groupId>

extensions/vertx-http/deployment/src/main/java/io/quarkus/devui/deployment/BuildTimeContentProcessor.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -503,6 +503,9 @@ private void addMenuSectionBuildTimeData(BuildTimeConstBuildItem internalBuildTi
503503
for (InternalPageBuildItem internalPageBuildItem : internalPages) {
504504
List<Page> pages = internalPageBuildItem.getPages();
505505
for (Page page : pages) {
506+
if (internalPageBuildItem.getMenuActionComponent() != null) {
507+
page.setMenuActionComponent(internalPageBuildItem.getMenuActionComponent());
508+
}
506509
sectionMenu.add(page);
507510
}
508511
internalBuildTimeData.addAllBuildTimeData(internalPageBuildItem.getBuildTimeData());

extensions/vertx-http/deployment/src/main/java/io/quarkus/devui/deployment/InternalPageBuildItem.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,16 @@ public final class InternalPageBuildItem extends MultiBuildItem {
1818
private final int position;
1919
private final List<Page> pages = new ArrayList<>();
2020
private final Map<String, Object> buildTimeData = new HashMap<>();
21+
private final String menuActionComponent;
2122

2223
public InternalPageBuildItem(String namespaceLabel, int position) {
24+
this(namespaceLabel, position, null);
25+
}
26+
27+
public InternalPageBuildItem(String namespaceLabel, int position, String menuActionComponent) {
2328
this.namespaceLabel = namespaceLabel;
2429
this.position = position;
30+
this.menuActionComponent = menuActionComponent;
2531
}
2632

2733
public void addPage(PageBuilder page) {
@@ -37,6 +43,10 @@ public List<Page> getPages() {
3743
return pages;
3844
}
3945

46+
public String getMenuActionComponent() {
47+
return menuActionComponent;
48+
}
49+
4050
public int getPosition() {
4151
return position;
4252
}

extensions/vertx-http/deployment/src/main/java/io/quarkus/devui/deployment/menu/ContinuousTestingProcessor.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,8 @@ public void continuousTestingState(
5252
@BuildStep(onlyIf = IsLocalDevelopment.class)
5353
InternalPageBuildItem createContinuousTestingPages() {
5454

55-
InternalPageBuildItem continuousTestingPages = new InternalPageBuildItem("Continuous Testing", 30);
55+
InternalPageBuildItem continuousTestingPages = new InternalPageBuildItem("Continuous Testing", 30,
56+
"qwc-continuous-testing-menu-action");
5657

5758
continuousTestingPages.addPage(Page.webComponentPageBuilder()
5859
.namespace(NAMESPACE)

extensions/vertx-http/deployment/src/main/java/io/quarkus/devui/deployment/menu/ExtensionsProcessor.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ public class ExtensionsProcessor {
3636
@BuildStep(onlyIf = IsLocalDevelopment.class)
3737
InternalPageBuildItem createExtensionsPages(ExtensionsBuildItem extensionsBuildItem) {
3838

39-
InternalPageBuildItem extensionsPages = new InternalPageBuildItem("Extensions", 10);
39+
InternalPageBuildItem extensionsPages = new InternalPageBuildItem("Extensions", 10, "qwc-extensions-menu-action");
4040

4141
// Extensions
4242
Map<ExtensionGroup, List<Extension>> response = Map.of(

extensions/vertx-http/dev-ui-resources/pom.xml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,13 @@
117117
<scope>runtime</scope>
118118
</dependency>
119119

120+
<!-- Loading indicators -->
121+
<dependency>
122+
<groupId>org.mvnpm</groupId>
123+
<artifactId>ldrs</artifactId>
124+
<scope>runtime</scope>
125+
</dependency>
126+
120127
<!-- Markdown it -->
121128
<dependency>
122129
<groupId>org.mvnpm</groupId>

extensions/vertx-http/dev-ui-resources/src/main/resources/dev-ui/controller/router-controller.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,11 @@ export class RouterController {
158158
Router.go({pathname: firstPage});
159159
}
160160

161+
go(page){
162+
let pageRef = this.getPageUrlFor(page);
163+
Router.go({pathname: pageRef});
164+
}
165+
161166
getFirstPageUrl(){
162167
for (let entry of RouterController.pageMap) {
163168
let value = entry[1];
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
import { LitElement, html, css} from 'lit';
2+
import {ring} from 'ldrs';
3+
4+
ring.register();
5+
6+
/**
7+
* This is the menu action on the Continuous Testing menu
8+
*/
9+
export class QwcContinuousTestingMenuAction extends LitElement {
10+
11+
static styles = css`
12+
.actionBtn{
13+
color: var(--lumo-contrast-25pct);
14+
}
15+
.ring {
16+
padding-right: 5px;
17+
padding-top: 5px;
18+
}
19+
`;
20+
21+
static properties = {
22+
_ctState: {state : true}
23+
}
24+
25+
constructor() {
26+
super();
27+
this._ctState = "stopped";
28+
}
29+
30+
connectedCallback() {
31+
super.connectedCallback();
32+
window.addEventListener('continuous-testing-state-change', this._onStateChanged);
33+
}
34+
35+
disconnectedCallback() {
36+
window.removeEventListener('continuous-testing-state-change', this._onStateChanged);
37+
super.disconnectedCallback();
38+
}
39+
40+
_onStateChanged = (event) => {
41+
this._ctState = event.detail.state;
42+
}
43+
44+
render(){
45+
let icon = "stop";
46+
let title = "Stop";
47+
if(this._ctState === "stopped"){
48+
icon = "play";
49+
title = "Start";
50+
}
51+
52+
if(this._ctState === "stopped" || this._ctState === "started"){
53+
return html`<vaadin-button
54+
title="${title} Continuous Testing " class="actionBtn"
55+
id="start-cnt-testing-btn"
56+
theme="icon tertiary small"
57+
@click="${this._startStopClicked}">
58+
<vaadin-icon icon="font-awesome-solid:${icon}"></vaadin-icon>
59+
</vaadin-button>`;
60+
}else{
61+
return html`<l-ring size="26" stroke="2" color="var(--lumo-contrast-25pct)" class="ring"></l-ring>`;
62+
}
63+
}
64+
65+
_startStopClicked(e){
66+
this.dispatchEvent(new CustomEvent('continuous-testing-start-stop', {
67+
detail: { requested: "start/stop" },
68+
bubbles: true,
69+
composed: true
70+
}));
71+
}
72+
73+
74+
}
75+
customElements.define('qwc-continuous-testing-menu-action', QwcContinuousTestingMenuAction);

extensions/vertx-http/dev-ui-resources/src/main/resources/dev-ui/qwc/qwc-continuous-testing.js

Lines changed: 61 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,11 @@ import { columnBodyRenderer } from '@vaadin/grid/lit.js';
1111
import { gridRowDetailsRenderer } from '@vaadin/grid/lit.js';
1212
import '@qomponent/qui-badge';
1313
import 'qui-ide-link';
14-
15-
14+
import 'qwc-no-data';
1615
import 'echarts-horizontal-stacked-bar';
16+
import {ring} from 'ldrs';
17+
18+
ring.register();
1719

1820
/**
1921
* This component shows the Continuous Testing Page
@@ -133,21 +135,42 @@ export class QwcContinuousTesting extends QwcHotReloadElement {
133135

134136
connectedCallback() {
135137
super.connectedCallback();
138+
window.addEventListener('continuous-testing-start-stop', this._onStartStopChanged);
136139
this._lastKnownState();
137140
this._createObservers();
138141
}
139142

140143
disconnectedCallback() {
144+
window.removeEventListener('continuous-testing-start-stop', this._onStartStopChanged);
141145
this._cancelObservers();
142146
super.disconnectedCallback();
143147
}
144148

149+
_onStartStopChanged = (event) => {
150+
if(this._testsEnabled){
151+
this._stop();
152+
}else {
153+
this._start();
154+
}
155+
}
156+
145157
_createObservers(){
146158
this._streamStateObserver = this.jsonRpc.streamState().onNext(jsonRpcResponse => {
147159
this._tests = jsonRpcResponse.result;
160+
this._broadcastState();
148161
});
149162
}
150163

164+
_broadcastState(){
165+
if(this._tests.inProgress){
166+
this._fireStateChange("busy");
167+
}else if(!this._tests.config.enabled){
168+
this._fireStateChange("stopped");
169+
}else if(this._tests.config.enabled){
170+
this._fireStateChange("started");
171+
}
172+
}
173+
151174
_cancelObservers(){
152175
this._streamStateObserver.cancel();
153176
if(this._streamResultsObserver){
@@ -159,6 +182,7 @@ export class QwcContinuousTesting extends QwcHotReloadElement {
159182
// Get last known
160183
this.jsonRpc.currentState().then(jsonRpcResponse => {
161184
this._tests = jsonRpcResponse.result;
185+
this._broadcastState();
162186
});
163187
}
164188

@@ -177,11 +201,16 @@ export class QwcContinuousTesting extends QwcHotReloadElement {
177201
}
178202

179203
_renderMenuBar(){
180-
if(this._testsReceived) {
204+
let items = [];
205+
if(this._testsEnabled) {
206+
items.push(... (this._testResult?.failed ?? []));
207+
items.push(... (this._testResult?.passed ?? []));
208+
items.push(... (this._testResult?.skipped ?? []));
209+
}
210+
if(items.length > 0){
181211
return html`
182212
<div class="menubar">
183213
<div>
184-
${this._renderStartStopButton()}
185214
${this._renderRunAllButton()}
186215
${this._renderRunFailedButton()}
187216
${this._renderToggleBrokenOnly()}
@@ -249,7 +278,23 @@ export class QwcContinuousTesting extends QwcHotReloadElement {
249278
</vaadin-grid>`;
250279

251280
}else{
252-
return html`No tests`;
281+
return html`<qwc-no-data message="Continuous Testing is not running. Click the Start button or press [r] in the console to start."
282+
link="https://quarkus.io/guides/continuous-testing"
283+
linkText="Read more about Continuous Testing">
284+
${this._renderPlayButton()}
285+
</qwc-no-data>
286+
`
287+
}
288+
}
289+
290+
_renderPlayButton(){
291+
if(!this._busy && !this._testsEnabled){
292+
return html`<vaadin-button theme="tertiary" @click=${this._start}>
293+
<vaadin-icon icon="font-awesome-solid:play"></vaadin-icon>
294+
Start
295+
</vaadin-button>`;
296+
}else{
297+
return html`<l-ring size="26" stroke="2" color="var(--lumo-contrast-25pct)" class="ring"></l-ring>`;
253298
}
254299
}
255300

@@ -340,17 +385,6 @@ export class QwcContinuousTesting extends QwcHotReloadElement {
340385
</span>`;
341386
}
342387

343-
_renderStartStopButton(){
344-
return html`<vaadin-button
345-
id="start-cnt-testing-btn"
346-
theme="tertiary"
347-
@click="${!this._testsEnabled ? this._start : this._stop}"
348-
?disabled=${this._busy}>
349-
<vaadin-icon icon="font-awesome-solid:${!this._testsEnabled ? 'play' : 'stop'}"></vaadin-icon>
350-
${!this._testsEnabled ? 'Start' : 'Stop'}
351-
</vaadin-button>`;
352-
}
353-
354388
_renderRunAllButton(){
355389
if(this._testsEnabled){
356390
return html`<vaadin-button id="run-all-cnt-testing-btn" theme="tertiary" @click="${this._runAll}" ?disabled=${this._state.inProgress || this._busy}>
@@ -394,6 +428,7 @@ export class QwcContinuousTesting extends QwcHotReloadElement {
394428
_start(){
395429
if(!this._busy){
396430
this._busy = true;
431+
this._fireStateChange("busy");
397432
this.jsonRpc.start().then(jsonRpcResponse => {
398433
this._busy = false;
399434
});
@@ -403,12 +438,22 @@ export class QwcContinuousTesting extends QwcHotReloadElement {
403438
_stop(){
404439
if(!this._busy){
405440
this._busy = true;
441+
this._fireStateChange("busy");
406442
this.jsonRpc.stop().then(jsonRpcResponse => {
407443
this._busy = false;
444+
this._fireStateChange("stopped");
408445
});
409446
}
410447
}
411448

449+
_fireStateChange(state){
450+
this.dispatchEvent(new CustomEvent('continuous-testing-state-change', {
451+
detail: { state: state },
452+
bubbles: true,
453+
composed: true
454+
}));
455+
}
456+
412457
_runAll(){
413458
this._busy = true;
414459
this.jsonRpc.runAll().then(jsonRpcResponse => {

0 commit comments

Comments
 (0)