Skip to content

Commit b12d5b6

Browse files
Merge pull request quarkusio#47874 from phillip-kruger/argoal-chappie
Agroal assistant feature
2 parents cc4b1f6 + 30d438d commit b12d5b6

File tree

7 files changed

+269
-20
lines changed

7 files changed

+269
-20
lines changed

bom/dev-ui/pom.xml

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,8 @@
5151
<ansi-styles.version>4.3.0</ansi-styles.version>
5252
<color-convert.version>2.0.1</color-convert.version>
5353
<color-name.version>1.1.4</color-name.version>
54+
<dot.version>0.0.1</dot.version>
55+
<viz-js.version>3.12.0</viz-js.version>
5456
</properties>
5557

5658
<dependencyManagement>
@@ -344,6 +346,22 @@
344346
<version>${es-module-shims.version}</version>
345347
<scope>runtime</scope>
346348
</dependency>
349+
350+
<!-- Dot files render -->
351+
<dependency>
352+
<groupId>org.mvnpm.at.qomponent</groupId>
353+
<artifactId>qui-dot</artifactId>
354+
<version>${dot.version}</version>
355+
<scope>runtime</scope>
356+
</dependency>
357+
358+
<!-- Viz.js to render dot file -->
359+
<dependency>
360+
<groupId>org.mvnpm.at.viz-js</groupId>
361+
<artifactId>viz</artifactId>
362+
<version>${viz-js.version}</version>
363+
<scope>runtime</scope>
364+
</dependency>
347365
</dependencies>
348366
</dependencyManagement>
349367
</project>

extensions/agroal/deployment/pom.xml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,10 @@
4141
<groupId>io.quarkus</groupId>
4242
<artifactId>quarkus-agroal-spi</artifactId>
4343
</dependency>
44+
<dependency>
45+
<groupId>io.quarkus</groupId>
46+
<artifactId>quarkus-assistant-deployment-spi</artifactId>
47+
</dependency>
4448
<dependency>
4549
<groupId>io.quarkus</groupId>
4650
<artifactId>quarkus-narayana-jta-deployment</artifactId>

extensions/agroal/deployment/src/main/java/io/quarkus/agroal/deployment/devui/AgroalDevUIProcessor.java

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,15 @@
22

33
import io.quarkus.agroal.runtime.DataSourcesJdbcBuildTimeConfig;
44
import io.quarkus.agroal.runtime.dev.ui.DatabaseInspector;
5+
import io.quarkus.assistant.runtime.dev.Assistant;
56
import io.quarkus.deployment.IsLocalDevelopment;
67
import io.quarkus.deployment.annotations.BuildProducer;
78
import io.quarkus.deployment.annotations.BuildStep;
89
import io.quarkus.deployment.annotations.BuildSteps;
910
import io.quarkus.deployment.builditem.LaunchModeBuildItem;
1011
import io.quarkus.dev.spi.DevModeType;
1112
import io.quarkus.devui.spi.JsonRPCProvidersBuildItem;
13+
import io.quarkus.devui.spi.buildtime.BuildTimeActionBuildItem;
1214
import io.quarkus.devui.spi.page.CardPageBuildItem;
1315
import io.quarkus.devui.spi.page.Page;
1416

@@ -37,8 +39,32 @@ void devUI(DataSourcesJdbcBuildTimeConfig config,
3739
}
3840
}
3941

42+
@BuildStep
43+
void createBuildTimeActions(BuildProducer<BuildTimeActionBuildItem> buildTimeActionProducer) {
44+
BuildTimeActionBuildItem bta = new BuildTimeActionBuildItem();
45+
46+
// TODO: If currentInsertScript is empty, maybe send tables schema. This might mean we need to move this to runtime
47+
48+
bta.addAssistantAction("generateMoreData", (a, p) -> {
49+
Assistant assistant = (Assistant) a;
50+
return assistant.assistBuilder()
51+
.userMessage(USER_MESSAGE)
52+
.variables(p)
53+
.assist();
54+
});
55+
buildTimeActionProducer.produce(bta);
56+
}
57+
4058
@BuildStep
4159
JsonRPCProvidersBuildItem createJsonRPCService() {
4260
return new JsonRPCProvidersBuildItem(DatabaseInspector.class);
4361
}
62+
63+
private static final String USER_MESSAGE = """
64+
Given the provided sql script:
65+
{{currentInsertScript}}
66+
Can you add 10 more inserts into the script and return the result
67+
(including the provided entries, so update the script)
68+
Return the result in a field called `script`.
69+
""";
4470
}

extensions/agroal/deployment/src/main/resources/dev-ui/qwc-agroal-datasource.js

Lines changed: 143 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,17 @@ import '@vaadin/progress-bar';
1616
import '@vaadin/button';
1717
import '@qomponent/qui-alert';
1818
import '@vaadin/dialog';
19+
import '@qomponent/qui-dot';
20+
import 'qui-assistant-button';
21+
import 'qui-assistant-warning';
1922
import { dialogFooterRenderer, dialogHeaderRenderer, dialogRenderer } from '@vaadin/dialog/lit.js';
23+
import { observeState } from 'lit-element-state';
24+
import { assistantState } from 'assistant-state';
2025

2126
/**
2227
* Allows interaction with your Datasource
2328
*/
24-
export class QwcAgroalDatasource extends QwcHotReloadElement {
29+
export class QwcAgroalDatasource extends observeState(QwcHotReloadElement) {
2530
jsonRpc = new JsonRpc(this);
2631
configJsonRpc = new JsonRpc("devui-configuration");
2732

@@ -50,6 +55,12 @@ export class QwcAgroalDatasource extends QwcHotReloadElement {
5055
align-items: baseline;
5156
gap: 20px;
5257
}
58+
.tables {
59+
display: flex;
60+
flex-direction: column;
61+
justify-content: space-between;
62+
}
63+
5364
.tablesAndData {
5465
display: flex;
5566
height: 100%;
@@ -78,10 +89,8 @@ export class QwcAgroalDatasource extends QwcHotReloadElement {
7889
7990
.sqlInput {
8091
display: flex;
81-
justify-content: space-between;
82-
gap: 10px;
8392
align-items: center;
84-
padding-bottom: 20px;
93+
padding-bottom: 10px;
8594
border-bottom-style: dotted;
8695
border-bottom-color: var(--lumo-contrast-10pct);
8796
}
@@ -154,6 +163,7 @@ export class QwcAgroalDatasource extends QwcHotReloadElement {
154163
_dataSources: {state: true},
155164
_selectedDataSource: {state: true},
156165
_tables: {state: true},
166+
_dot: {state: true},
157167
_selectedTable: {state: true},
158168
_selectedTableIndex:{state: true},
159169
_selectedTableCols:{state: true},
@@ -169,14 +179,18 @@ export class QwcAgroalDatasource extends QwcHotReloadElement {
169179
_isAllowedDB: {state: true},
170180
_displaymessage: {state: true},
171181
_insertSQL: {state: true},
172-
_dialogOpened: {state: true}
182+
_showBusyLoadingDialog: {state: true},
183+
_showAssistantWarning: {state: true},
184+
_showImportSQLDialog: {state: true},
185+
_showErDiagramDialog: {state: true}
173186
};
174187

175188
constructor() {
176189
super();
177190
this._dataSources = null;
178191
this._selectedDataSource = null;
179192
this._tables = null;
193+
this._dot = null;
180194
this._selectedTable = null;
181195
this._selectedTableCols = null;
182196
this._selectedTableIndex = 0;
@@ -192,7 +206,10 @@ export class QwcAgroalDatasource extends QwcHotReloadElement {
192206
this._allowedHost = null;
193207
this._displaymessage = null;
194208
this._insertSQL = null;
195-
this._dialogOpened = false;
209+
this._showBusyLoadingDialog = null;
210+
this._showAssistantWarning = false;
211+
this._showImportSQLDialog = false;
212+
this._showErDiagramDialog = false;
196213
}
197214

198215
connectedCallback() {
@@ -234,34 +251,55 @@ export class QwcAgroalDatasource extends QwcHotReloadElement {
234251
</div>
235252
${this._renderDataOrWarning()}
236253
</div>
237-
${this._renderImportSqlDialog()}`;
254+
${this._renderBusyLoadingDialog()}
255+
${this._renderImportSqlDialog()}
256+
${this._renderDotViewerDialog()}`;
238257
} else {
239-
return html`<div style="color: var(--lumo-secondary-text-color);width: 95%;" >
240-
<div>Fetching data sources...</div>
258+
return this._renderProgressBar("Fetching data sources...");
259+
}
260+
}
261+
262+
_renderProgressBar(message){
263+
return html`<div style="color: var(--lumo-secondary-text-color);width: 95%;" >
264+
<div>${message}</div>
241265
<vaadin-progress-bar indeterminate></vaadin-progress-bar>
242266
</div>`;
267+
}
268+
269+
_renderBusyLoadingDialog(){
270+
if(this._showBusyLoadingDialog){
271+
return html`<vaadin-dialog
272+
resizable
273+
draggable
274+
header-title="Loading"
275+
.opened="${true}"
276+
277+
${dialogRenderer(this._renderBusyLoadingDialogContents)}
278+
></vaadin-dialog>`;
243279
}
244280
}
245281

246282
_renderImportSqlDialog(){
247-
if(this._insertSQL){
283+
if(this._insertSQL && !this._showBusyLoadingDialog){
248284
return html`
249285
<vaadin-dialog
250286
resizable
251287
draggable
252288
header-title="Import SQL Script"
253-
.opened="${this._dialogOpened}"
289+
.opened="${this._showImportSQLDialog}"
254290
@opened-changed="${(event) => {
255-
this._dialogOpened = event.detail.value;
291+
this._showImportSQLDialog = event.detail.value;
256292
}}"
257293
${dialogHeaderRenderer(
258294
() => html`
295+
${this._renderAssistantWarning()}
259296
<vaadin-button title="Save insert script" theme="tertiary" @click="${this._saveInsertScript}">
260297
<vaadin-icon icon="font-awesome-solid:floppy-disk"></vaadin-icon>
261298
</vaadin-button>
262299
<vaadin-button title="Copy insert script" theme="tertiary" @click="${this._copyInsertScript}">
263300
<vaadin-icon icon="font-awesome-solid:copy"></vaadin-icon>
264301
</vaadin-button>
302+
${this._renderAssistantButton()}
265303
<vaadin-button theme="tertiary" @click="${this._closeDialog}">
266304
<vaadin-icon icon="font-awesome-solid:xmark"></vaadin-icon>
267305
</vaadin-button>`,
@@ -272,6 +310,61 @@ export class QwcAgroalDatasource extends QwcHotReloadElement {
272310
}
273311
}
274312

313+
_renderDotViewerDialog(){
314+
if(this._dot && !this._showBusyLoadingDialog){
315+
return html`
316+
<vaadin-dialog
317+
resizable
318+
draggable
319+
header-title="ER Diagram"
320+
.opened="${this._showErDiagramDialog}"
321+
@opened-changed="${(event) => {
322+
this._showErDiagramDialog = event.detail.value;
323+
}}"
324+
${dialogHeaderRenderer(
325+
() => html`
326+
<vaadin-button theme="tertiary" @click="${this._closeDialog}">
327+
<vaadin-icon icon="font-awesome-solid:xmark"></vaadin-icon>
328+
</vaadin-button>`,
329+
[]
330+
)}
331+
${dialogRenderer(this._renderDotViewerDialogContents)}
332+
></vaadin-dialog>`;
333+
}
334+
}
335+
336+
_renderAssistantButton(){
337+
if(assistantState.current.isConfigured && this._insertSQL){
338+
return html`<qui-assistant-button title="Use Quarkus Assistant to generate more data" @click="${this._generateMoreData}"></qui-assistant-button>`;
339+
}
340+
}
341+
342+
_renderAssistantWarning(){
343+
if(this._showAssistantWarning){
344+
return html`<qui-assistant-warning></qui-assistant-warning>`;
345+
}
346+
}
347+
348+
_generateMoreData(){
349+
if(this._insertSQL){
350+
this._showBusyLoadingDialog = "Quarkus Assistant is generating more data ... please wait";
351+
352+
this.jsonRpc.generateMoreData({
353+
currentInsertScript:this._insertSQL
354+
}).then(jsonRpcResponse => {
355+
const script = jsonRpcResponse.result.script;
356+
if (Array.isArray(script)) {
357+
this._insertSQL = script.join('\n');
358+
} else {
359+
this._insertSQL = script;
360+
}
361+
this._showBusyLoadingDialog = null;
362+
this._showImportSQLDialog = true;
363+
this._showAssistantWarning = true;
364+
});
365+
}
366+
}
367+
275368
_saveInsertScript(){
276369
try {
277370
const blob = new Blob([this.value], { type: 'text/sql' });
@@ -305,18 +398,30 @@ export class QwcAgroalDatasource extends QwcHotReloadElement {
305398

306399
_closeDialog(){
307400
this._insertSQL = null;
308-
this._dialogOpened = false;
401+
this._dot = null;
402+
this._showImportSQLDialog = false;
403+
this._showErDiagramDialog = false;
404+
this._showAssistantWarning = false;
309405
}
310406

311407
_renderImportSqlDialogContents(){
312408
return html`<qui-code-block content="${this._insertSQL}" mode="sql" theme="dark"></qui-code-block>`;
313409
}
314410

411+
_renderDotViewerDialogContents(){
412+
return html`<qui-dot dot="${this._dot}"></qui-dot>`;
413+
}
414+
415+
_renderBusyLoadingDialogContents(){
416+
return this._renderProgressBar(this._showBusyLoadingDialog);
417+
}
418+
315419
_renderDataOrWarning(){
316420
if(this._isAllowedDB){
317421
return html`<div class="tablesAndData">
318422
<div class="tables">
319423
${this._renderTables()}
424+
${this._renderGenerateErDiagramButton()}
320425
</div>
321426
<div class="tableData">
322427
${this._renderDataAndDefinition()}
@@ -377,6 +482,15 @@ export class QwcAgroalDatasource extends QwcHotReloadElement {
377482

378483
}
379484

485+
_renderGenerateErDiagramButton(){
486+
if(this._selectedDataSource){
487+
return html`<vaadin-button @click=${this._generateErDiagram} title="Generate an ER Diagram for the tables">
488+
<vaadin-icon icon="font-awesome-solid:table" slot="prefix"></vaadin-icon>
489+
ER Diagram
490+
</vaadin-button>`;
491+
}
492+
}
493+
380494
_renderDataAndDefinition(){
381495
return html`<vaadin-tabsheet class="fill" theme="bordered">
382496
<vaadin-button slot="suffix" theme="icon" title="Refresh" aria-label="Refresh">
@@ -487,12 +601,12 @@ export class QwcAgroalDatasource extends QwcHotReloadElement {
487601
<qui-code-block @shiftEnter=${this._shiftEnterPressed} content="${this._currentSQL}"
488602
class="font-large cursor-text" id="sql" mode="sql" theme="dark"
489603
value='${this._currentSQL}' editable></qui-code-block>
490-
<vaadin-button class="no-margin" slot="suffix" theme="icon" aria-label="Clear">
604+
<vaadin-button class="no-margin" slot="suffix" theme="icon tertiary small" aria-label="Clear">
491605
<vaadin-tooltip .hoverDelay=${500} slot="tooltip" text="Clear"></vaadin-tooltip>
492606
<vaadin-icon class="small-icon" @click=${this._clearSqlInput}
493-
icon="font-awesome-solid:trash"></vaadin-icon>
607+
icon="font-awesome-solid:broom"></vaadin-icon>
494608
</vaadin-button>
495-
<vaadin-button class="no-margin" slot="suffix" theme="icon" aria-label="Run">
609+
<vaadin-button class="no-margin" slot="suffix" theme="icon tertiary small" aria-label="Run">
496610
<vaadin-tooltip .hoverDelay=${500} slot="tooltip" text="Run"></vaadin-tooltip>
497611
<vaadin-icon class="small-icon" @click=${this._executeClicked}
498612
icon="font-awesome-solid:play"></vaadin-icon>
@@ -503,6 +617,18 @@ export class QwcAgroalDatasource extends QwcHotReloadElement {
503617
}
504618
}
505619

620+
_generateErDiagram(){
621+
if(this._selectedDataSource){
622+
this._showBusyLoadingDialog = "Generating ER Diagram ... please wait";
623+
this._insertSQL = null;
624+
this.jsonRpc.generateDot({datasource:this._selectedDataSource.name}).then(jsonRpcResponse => {
625+
this._showBusyLoadingDialog = null;
626+
this._dot = jsonRpcResponse.result;
627+
this._showErDiagramDialog = true;
628+
});
629+
}
630+
}
631+
506632
_handleAllowSqlChange(){
507633
this.configJsonRpc.updateProperty({
508634
'name': '%dev.quarkus.datasource.dev-ui.allow-sql',
@@ -673,7 +799,7 @@ export class QwcAgroalDatasource extends QwcHotReloadElement {
673799
if(this._selectedDataSource){
674800
this.jsonRpc.getInsertScript({datasource:this._selectedDataSource.name}).then(jsonRpcResponse => {
675801
this._insertSQL = jsonRpcResponse.result;
676-
this._dialogOpened = true;
802+
this._showImportSQLDialog = true;
677803
});
678804
}
679805
}

0 commit comments

Comments
 (0)