Skip to content

Commit 09181ee

Browse files
Agroal - Add assistant feature: Generate Test data
Signed-off-by: Phillip Kruger <[email protected]>
1 parent c4edfd8 commit 09181ee

File tree

9 files changed

+263
-16
lines changed

9 files changed

+263
-16
lines changed

bom/dev-ui/pom.xml

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
<codeblock.version>1.1.1</codeblock.version>
3434
<qomponent.version>1.0.4</qomponent.version>
3535
<directory-tree.version>1.0.3</directory-tree.version>
36+
<dot.version>0.0.1</dot.version>
3637
<hpcc-js-wasm.version>2.15.3</hpcc-js-wasm.version>
3738
<yargs.version>17.7.2</yargs.version>
3839
<cliui.version>8.0.1</cliui.version>
@@ -50,6 +51,7 @@
5051
<ansi-styles.version>4.3.0</ansi-styles.version>
5152
<color-convert.version>2.0.1</color-convert.version>
5253
<color-name.version>1.1.4</color-name.version>
54+
<viz-js.version>3.12.0</viz-js.version>
5355
</properties>
5456

5557
<dependencyManagement>
@@ -277,6 +279,14 @@
277279
<scope>runtime</scope>
278280
</dependency>
279281

282+
<!-- Dot files render -->
283+
<dependency>
284+
<groupId>org.mvnpm.at.qomponent</groupId>
285+
<artifactId>qui-dot</artifactId>
286+
<version>${dot.version}</version>
287+
<scope>runtime</scope>
288+
</dependency>
289+
280290
<!-- Markdown render -->
281291
<dependency>
282292
<groupId>org.mvnpm</groupId>
@@ -335,6 +345,14 @@
335345
<version>${es-module-shims.version}</version>
336346
<scope>runtime</scope>
337347
</dependency>
348+
349+
<!-- Viz.js to render dot file -->
350+
<dependency>
351+
<groupId>org.mvnpm.at.viz-js</groupId>
352+
<artifactId>viz</artifactId>
353+
<version>${viz-js.version}</version>
354+
<scope>runtime</scope>
355+
</dependency>
338356
</dependencies>
339357
</dependencyManagement>
340358
</project>

extensions/agroal/deployment/pom.xml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,10 @@
2525
<groupId>io.quarkus</groupId>
2626
<artifactId>quarkus-datasource-deployment</artifactId>
2727
</dependency>
28+
<dependency>
29+
<groupId>io.quarkus</groupId>
30+
<artifactId>quarkus-assistant-deployment</artifactId>
31+
</dependency>
2832
<dependency>
2933
<groupId>io.quarkus</groupId>
3034
<artifactId>quarkus-agroal</artifactId>

extensions/agroal/deployment/src/main/java/io/quarkus/agroal/deployment/AgroalProcessor.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,6 @@ class AgroalProcessor {
7373

7474
private static final Logger log = Logger.getLogger(AgroalProcessor.class);
7575

76-
private static final String OPEN_TELEMETRY_DRIVER = "io.opentelemetry.instrumentation.jdbc.OpenTelemetryDriver";
7776
private static final DotName DATA_SOURCE = DotName.createSimple(javax.sql.DataSource.class.getName());
7877
private static final DotName AGROAL_DATA_SOURCE = DotName.createSimple(AgroalDataSource.class.getName());
7978

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

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,19 @@
11
package io.quarkus.agroal.deployment.devui;
22

3+
import java.util.Optional;
4+
35
import io.quarkus.agroal.runtime.DataSourcesJdbcBuildTimeConfig;
46
import io.quarkus.agroal.runtime.dev.ui.DatabaseInspector;
7+
import io.quarkus.assistant.deployment.Assistant;
8+
import io.quarkus.assistant.deployment.AssistantBuildItem;
59
import io.quarkus.deployment.IsLocalDevelopment;
610
import io.quarkus.deployment.annotations.BuildProducer;
711
import io.quarkus.deployment.annotations.BuildStep;
812
import io.quarkus.deployment.annotations.BuildSteps;
913
import io.quarkus.deployment.builditem.LaunchModeBuildItem;
1014
import io.quarkus.dev.spi.DevModeType;
1115
import io.quarkus.devui.spi.JsonRPCProvidersBuildItem;
16+
import io.quarkus.devui.spi.buildtime.BuildTimeActionBuildItem;
1217
import io.quarkus.devui.spi.page.CardPageBuildItem;
1318
import io.quarkus.devui.spi.page.Page;
1419

@@ -37,8 +42,35 @@ void devUI(DataSourcesJdbcBuildTimeConfig config,
3742
}
3843
}
3944

45+
@BuildStep
46+
void createBuildTimeActions(Optional<AssistantBuildItem> assistantBuildItem,
47+
BuildProducer<BuildTimeActionBuildItem> buildTimeActionProducer) {
48+
49+
if (assistantBuildItem.isPresent()) {
50+
BuildTimeActionBuildItem bta = new BuildTimeActionBuildItem();
51+
52+
Assistant assistant = assistantBuildItem.get().getAssistant();
53+
54+
// TODO: If currentInsertScript is empty, maybe send tables schema
55+
56+
bta.addAction("generateMoreData", params -> {
57+
return assistant.assist(USER_MESSAGE, params);
58+
});
59+
60+
buildTimeActionProducer.produce(bta);
61+
}
62+
}
63+
4064
@BuildStep
4165
JsonRPCProvidersBuildItem createJsonRPCService() {
4266
return new JsonRPCProvidersBuildItem(DatabaseInspector.class);
4367
}
68+
69+
private static final String USER_MESSAGE = """
70+
Given the provided sql script:
71+
{{currentInsertScript}}
72+
Can you add 10 more inserts into the script and return the result
73+
(including the provided entries, so update the script)
74+
Return the result in a field called `script`.
75+
""";
4476
}

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

Lines changed: 128 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,15 @@ import '@vaadin/progress-bar';
1616
import '@vaadin/button';
1717
import '@qomponent/qui-alert';
1818
import '@vaadin/dialog';
19+
import '@qomponent/qui-dot';
1920
import { dialogFooterRenderer, dialogHeaderRenderer, dialogRenderer } from '@vaadin/dialog/lit.js';
21+
import { devuiState } from 'devui-state';
22+
import { observeState } from 'lit-element-state';
2023

2124
/**
2225
* Allows interaction with your Datasource
2326
*/
24-
export class QwcAgroalDatasource extends QwcHotReloadElement {
27+
export class QwcAgroalDatasource extends observeState(QwcHotReloadElement) {
2528
jsonRpc = new JsonRpc(this);
2629
configJsonRpc = new JsonRpc("devui-configuration");
2730

@@ -50,6 +53,12 @@ export class QwcAgroalDatasource extends QwcHotReloadElement {
5053
align-items: baseline;
5154
gap: 20px;
5255
}
56+
.tables {
57+
display: flex;
58+
flex-direction: column;
59+
justify-content: space-between;
60+
}
61+
5362
.tablesAndData {
5463
display: flex;
5564
height: 100%;
@@ -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,17 @@ 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+
_showImportSQLDialog: {state: true},
184+
_showErDiagramDialog: {state: true}
173185
};
174186

175187
constructor() {
176188
super();
177189
this._dataSources = null;
178190
this._selectedDataSource = null;
179191
this._tables = null;
192+
this._dot = null;
180193
this._selectedTable = null;
181194
this._selectedTableCols = null;
182195
this._selectedTableIndex = 0;
@@ -192,7 +205,9 @@ export class QwcAgroalDatasource extends QwcHotReloadElement {
192205
this._allowedHost = null;
193206
this._displaymessage = null;
194207
this._insertSQL = null;
195-
this._dialogOpened = false;
208+
this._showBusyLoadingDialog = false;
209+
this._showImportSQLDialog = false;
210+
this._showErDiagramDialog = false;
196211
}
197212

198213
connectedCallback() {
@@ -234,25 +249,44 @@ export class QwcAgroalDatasource extends QwcHotReloadElement {
234249
</div>
235250
${this._renderDataOrWarning()}
236251
</div>
237-
${this._renderImportSqlDialog()}`;
252+
${this._renderBusyLoadingDialog()}
253+
${this._renderImportSqlDialog()}
254+
${this._renderDotViewerDialog()}`;
238255
} else {
239-
return html`<div style="color: var(--lumo-secondary-text-color);width: 95%;" >
240-
<div>Fetching data sources...</div>
256+
return this._renderProgressBar("Fetching data sources...");
257+
}
258+
}
259+
260+
_renderProgressBar(message){
261+
return html`<div style="color: var(--lumo-secondary-text-color);width: 95%;" >
262+
<div>${message}</div>
241263
<vaadin-progress-bar indeterminate></vaadin-progress-bar>
242264
</div>`;
265+
}
266+
267+
_renderBusyLoadingDialog(){
268+
if(this._showBusyLoadingDialog){
269+
return html`<vaadin-dialog
270+
resizable
271+
draggable
272+
header-title="Loading"
273+
.opened="${true}"
274+
275+
${dialogRenderer(this._renderBusyLoadingDialogContents)}
276+
></vaadin-dialog>`;
243277
}
244278
}
245279

246280
_renderImportSqlDialog(){
247-
if(this._insertSQL){
281+
if(this._insertSQL && !this._showBusyLoadingDialog){
248282
return html`
249283
<vaadin-dialog
250284
resizable
251285
draggable
252286
header-title="Import SQL Script"
253-
.opened="${this._dialogOpened}"
287+
.opened="${this._showImportSQLDialog}"
254288
@opened-changed="${(event) => {
255-
this._dialogOpened = event.detail.value;
289+
this._showImportSQLDialog = event.detail.value;
256290
}}"
257291
${dialogHeaderRenderer(
258292
() => html`
@@ -262,6 +296,7 @@ export class QwcAgroalDatasource extends QwcHotReloadElement {
262296
<vaadin-button title="Copy insert script" theme="tertiary" @click="${this._copyInsertScript}">
263297
<vaadin-icon icon="font-awesome-solid:copy"></vaadin-icon>
264298
</vaadin-button>
299+
${this._renderAssistantButton()}
265300
<vaadin-button theme="tertiary" @click="${this._closeDialog}">
266301
<vaadin-icon icon="font-awesome-solid:xmark"></vaadin-icon>
267302
</vaadin-button>`,
@@ -272,6 +307,56 @@ export class QwcAgroalDatasource extends QwcHotReloadElement {
272307
}
273308
}
274309

310+
_renderDotViewerDialog(){
311+
if(this._dot && !this._showBusyLoadingDialog){
312+
return html`
313+
<vaadin-dialog
314+
resizable
315+
draggable
316+
header-title="ER Diagram"
317+
.opened="${this._showErDiagramDialog}"
318+
@opened-changed="${(event) => {
319+
this._showErDiagramDialog = event.detail.value;
320+
}}"
321+
${dialogHeaderRenderer(
322+
() => html`
323+
<vaadin-button theme="tertiary" @click="${this._closeDialog}">
324+
<vaadin-icon icon="font-awesome-solid:xmark"></vaadin-icon>
325+
</vaadin-button>`,
326+
[]
327+
)}
328+
${dialogRenderer(this._renderDotViewerDialogContents)}
329+
></vaadin-dialog>`;
330+
}
331+
}
332+
333+
_renderAssistantButton(){
334+
if(devuiState.applicationInfo.assistantAvailable && this._insertSQL){
335+
return html`<vaadin-button title="Generate mode data" theme="tertiary" @click="${this._generateMoreData}">
336+
<vaadin-icon icon="font-awesome-solid:wand-magic-sparkles"></vaadin-icon>
337+
</vaadin-button>`;
338+
}
339+
}
340+
341+
_generateMoreData(){
342+
if(this._insertSQL){
343+
this._showBusyLoadingDialog = true;
344+
345+
this.jsonRpc.generateMoreData({
346+
currentInsertScript:this._insertSQL
347+
}).then(jsonRpcResponse => {
348+
const script = jsonRpcResponse.result.script;
349+
if (Array.isArray(script)) {
350+
this._insertSQL = script.join('\n');
351+
} else {
352+
this._insertSQL = script;
353+
}
354+
this._showBusyLoadingDialog = false;
355+
this._showImportSQLDialog = true;
356+
});
357+
}
358+
}
359+
275360
_saveInsertScript(){
276361
try {
277362
const blob = new Blob([this.value], { type: 'text/sql' });
@@ -305,18 +390,29 @@ export class QwcAgroalDatasource extends QwcHotReloadElement {
305390

306391
_closeDialog(){
307392
this._insertSQL = null;
308-
this._dialogOpened = false;
393+
this._dot = null;
394+
this._showImportSQLDialog = false;
395+
this._showErDiagramDialog = false;
309396
}
310397

311398
_renderImportSqlDialogContents(){
312399
return html`<qui-code-block content="${this._insertSQL}" mode="sql" theme="dark"></qui-code-block>`;
313400
}
314401

402+
_renderDotViewerDialogContents(){
403+
return html`<qui-dot dot="${this._dot}"></qui-dot>`;
404+
}
405+
406+
_renderBusyLoadingDialogContents(){
407+
return this._renderProgressBar("Busy loading... please hold on");
408+
}
409+
315410
_renderDataOrWarning(){
316411
if(this._isAllowedDB){
317412
return html`<div class="tablesAndData">
318413
<div class="tables">
319414
${this._renderTables()}
415+
${this._renderGenerateErDiagramButton()}
320416
</div>
321417
<div class="tableData">
322418
${this._renderDataAndDefinition()}
@@ -377,6 +473,15 @@ export class QwcAgroalDatasource extends QwcHotReloadElement {
377473

378474
}
379475

476+
_renderGenerateErDiagramButton(){
477+
if(this._selectedDataSource){
478+
return html`<vaadin-button @click=${this._generateErDiagram} title="Generate an ER Diagram for the tables">
479+
<vaadin-icon icon="font-awesome-solid:table" slot="prefix"></vaadin-icon>
480+
ER Diagram
481+
</vaadin-button>`;
482+
}
483+
}
484+
380485
_renderDataAndDefinition(){
381486
return html`<vaadin-tabsheet class="fill" theme="bordered">
382487
<vaadin-button slot="suffix" theme="icon" title="Refresh" aria-label="Refresh">
@@ -503,6 +608,18 @@ export class QwcAgroalDatasource extends QwcHotReloadElement {
503608
}
504609
}
505610

611+
_generateErDiagram(){
612+
if(this._selectedDataSource){
613+
this._showBusyLoadingDialog = true;
614+
this._insertSQL = null;
615+
this.jsonRpc.generateDot({datasource:this._selectedDataSource.name}).then(jsonRpcResponse => {
616+
this._showBusyLoadingDialog = false;
617+
this._dot = jsonRpcResponse.result;
618+
this._showErDiagramDialog = true;
619+
});
620+
}
621+
}
622+
506623
_handleAllowSqlChange(){
507624
this.configJsonRpc.updateProperty({
508625
'name': '%dev.quarkus.datasource.dev-ui.allow-sql',
@@ -671,7 +788,7 @@ export class QwcAgroalDatasource extends QwcHotReloadElement {
671788
if(this._selectedDataSource){
672789
this.jsonRpc.getInsertScript({datasource:this._selectedDataSource.name}).then(jsonRpcResponse => {
673790
this._insertSQL = jsonRpcResponse.result;
674-
this._dialogOpened = true;
791+
this._showImportSQLDialog = true;
675792
});
676793
}
677794
}

0 commit comments

Comments
 (0)