Skip to content

Commit

Permalink
UI improvements and other miscellaneous refactoring.
Browse files Browse the repository at this point in the history
  • Loading branch information
pacphi committed Dec 15, 2024
1 parent d3ffa33 commit 7843ba3
Show file tree
Hide file tree
Showing 19 changed files with 363 additions and 188 deletions.
10 changes: 6 additions & 4 deletions build.gradle
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
plugins {
id 'java'
id 'com.vaadin' version '24.5.7'
id 'com.vaadin' version '24.5.8'
id 'org.cyclonedx.bom' version '1.10.0'
id 'com.gorylenko.gradle-git-properties' version '2.4.2'
id 'org.springframework.boot' version '3.3.5'
id 'org.springframework.boot' version '3.4.0'
id 'io.spring.dependency-management' version '1.1.6'
id 'org.eclipse.jkube.kubernetes' version '1.17.0'
}
Expand All @@ -21,15 +21,17 @@ repositories {
}

ext {
set('springCloudVersion', "2023.0.3")
set('vaadinVersion', "24.5.4")
set('springCloudVersion', "2024.0.0")
set('vaadinVersion', "24.5.8")
}

dependencies {
implementation 'org.springframework.boot:spring-boot-starter-actuator'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.cloud:spring-cloud-starter-openfeign'
implementation 'org.apache.commons:commons-collections4:4.4'
implementation 'io.github.openfeign:feign-hc5:13.5'
implementation 'com.playtika.reactivefeign:feign-reactor-spring-cloud-starter:4.2.1'
implementation 'com.vaadin:vaadin-spring-boot-starter'
implementation 'org.apache.commons:commons-lang3'
implementation 'org.commonmark:commonmark:0.24.0'
Expand Down
2 changes: 2 additions & 0 deletions docs/BUILD.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
## How to Build

```bash
npm install @vaadin/hilla-lit-form
npm install @vaadin/hilla-react-signals
./gradlew clean build
```

Expand Down
22 changes: 22 additions & 0 deletions src/main/frontend/flow/markdown-component.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import React, {useEffect, useState} from 'react';
import {ReactAdapterElement} from 'Frontend/generated/flow/ReactAdapter';
import {effect, signal} from "@vaadin/hilla-react-signals";
import Markdown from "react-markdown";

class MarkdownElement extends ReactAdapterElement {

markdown = signal('');

protected override render() {
// In a React component, we could use the signal value directly,
// but it doesn't trigger an update in the ReactAdapterElement render method.
// Instead, pass the signal value to useState for React.
const [content, setContent] = useState('');
useEffect(() => effect(() => {
setContent(this.markdown.value);
}), []);
return <Markdown>{content}</Markdown>;
}
}

customElements.define('markdown-component', MarkdownElement);
2 changes: 2 additions & 0 deletions src/main/java/org/cftoolsuite/RobertUiApplication.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,11 @@
import com.vaadin.flow.server.PWA;
import com.vaadin.flow.theme.Theme;
import com.vaadin.flow.theme.lumo.Lumo;
import reactivefeign.spring.config.EnableReactiveFeignClients;

@SpringBootApplication
@EnableFeignClients
@EnableReactiveFeignClients
@ConfigurationPropertiesScan
@Theme(themeClass = Lumo.class, variant = Lumo.DARK)
@PWA(name = "A simple user interface to interact with a robert instance", shortName = "robert-ui")
Expand Down
6 changes: 4 additions & 2 deletions src/main/java/org/cftoolsuite/client/RefactorClient.java
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
package org.cftoolsuite.client;

import java.util.Map;
import java.util.Set;

import org.cftoolsuite.domain.GitRequest;
import org.cftoolsuite.domain.GitResponse;
import org.cftoolsuite.domain.IngestRequest;
import org.cftoolsuite.domain.LanguageExtensions;
import org.cftoolsuite.domain.chat.Inquiry;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
Expand All @@ -20,8 +22,8 @@ public interface RefactorClient {
@PostMapping(value = "/ingest")
ResponseEntity<Void> ingest(@RequestBody IngestRequest request);

@GetMapping("/chat")
ResponseEntity<String> chat(@RequestParam("q") String message);
@PostMapping("/api/chat")
public ResponseEntity<String> chat(@RequestBody Inquiry inquiry);

@PostMapping(value = "/refactor")
ResponseEntity<GitResponse> refactor(@RequestBody GitRequest request);
Expand Down
15 changes: 15 additions & 0 deletions src/main/java/org/cftoolsuite/client/RefactorStreamingClient.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package org.cftoolsuite.client;

import org.cftoolsuite.domain.chat.Inquiry;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import reactivefeign.spring.config.ReactiveFeignClient;
import reactor.core.publisher.Flux;

@ReactiveFeignClient(name="refactor-streaming-service", url="${refactor.service.url}")
public interface RefactorStreamingClient {

@PostMapping("/api/stream/chat")
public Flux<String> streamResponseToQuestion(@RequestBody Inquiry inquiry);
}

39 changes: 0 additions & 39 deletions src/main/java/org/cftoolsuite/config/OpenFeign.java

This file was deleted.

4 changes: 4 additions & 0 deletions src/main/java/org/cftoolsuite/domain/chat/FilterMetadata.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package org.cftoolsuite.domain.chat;

public record FilterMetadata(String key, Object value) {
}
6 changes: 6 additions & 0 deletions src/main/java/org/cftoolsuite/domain/chat/Inquiry.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package org.cftoolsuite.domain.chat;

import java.util.List;

public record Inquiry(String question, List<FilterMetadata> filter) {
}
18 changes: 11 additions & 7 deletions src/main/java/org/cftoolsuite/ui/MainLayout.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package org.cftoolsuite.ui;

import com.vaadin.flow.component.html.Image;
import com.vaadin.flow.server.StreamResource;
import org.cftoolsuite.client.ModeClient;
import org.cftoolsuite.ui.view.ChatView;
import org.cftoolsuite.ui.view.HomeView;
Expand All @@ -8,10 +10,8 @@
import org.cftoolsuite.ui.view.SearchView;

import com.vaadin.flow.component.Component;
import com.vaadin.flow.component.accordion.Accordion;
import com.vaadin.flow.component.applayout.AppLayout;
import com.vaadin.flow.component.applayout.DrawerToggle;
import com.vaadin.flow.component.details.DetailsVariant;
import com.vaadin.flow.component.html.Div;
import com.vaadin.flow.component.html.Span;
import com.vaadin.flow.component.icon.Icon;
Expand All @@ -28,9 +28,6 @@ public class MainLayout extends AppLayout {
public MainLayout(ModeClient modeClient) {
Tab homeTab = createTab(VaadinIcon.HOME.create(), "Home", HomeView.class);

Accordion accordion = new Accordion();
accordion.setSizeFull();

Tabs actionTabs = createTabs();
if (modeClient.isAdvancedModeConfigured()) {
Tab ingestTab = createTab(VaadinIcon.PLUG.create(),"Ingest", IngestView.class);
Expand All @@ -42,10 +39,9 @@ public MainLayout(ModeClient modeClient) {
}
Tab refactorTab = createTab(VaadinIcon.PLAY.create(), "Refactor", RefactorView.class);
actionTabs.add(refactorTab);
accordion.add("Actions", actionTabs).addThemeVariants(DetailsVariant.REVERSE);

addToNavbar(true, homeTab, new DrawerToggle());
addToDrawer(accordion);
addToDrawer(getLogoImage(), actionTabs);
}

private Tabs createTabs() {
Expand All @@ -72,4 +68,12 @@ private Tab createTab(Icon icon, String label, Class<? extends Component> layout
return tab;
}

private Image getLogoImage() {
StreamResource imageResource = new StreamResource("robert.png",
() -> getClass().getResourceAsStream("/static/robert.png"));
Image logo = new Image(imageResource, "Logo");
logo.setWidth("240px");
return logo;
}

}
36 changes: 25 additions & 11 deletions src/main/java/org/cftoolsuite/ui/component/Markdown.java
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
package org.cftoolsuite.ui.component;

import com.vaadin.flow.component.Composite;
import com.vaadin.flow.component.html.Div;
import org.commonmark.parser.Parser;
import org.commonmark.renderer.html.HtmlRenderer;
import com.vaadin.flow.component.Tag;
import com.vaadin.flow.component.dependency.JsModule;
import com.vaadin.flow.component.dependency.NpmPackage;
import com.vaadin.flow.component.react.ReactAdapterComponent;

public class Markdown extends Composite<Div> {
@NpmPackage(value = "react-markdown", version = "9.0.1")
@JsModule("./flow/markdown-component.tsx")
@Tag("markdown-component")
public class Markdown extends ReactAdapterComponent {

Parser parser = Parser.builder().build();
HtmlRenderer renderer = HtmlRenderer.builder().build();
private String markdown = "";

public Markdown() {
}
Expand All @@ -18,8 +20,20 @@ public Markdown(String markdown) {
}

public void setMarkdown(String markdown) {
getContent().getElement().setProperty("innerHTML",
renderer.render(parser.parse(markdown))
);
this.markdown = markdown;
getElement().executeJs("this.markdown.value = $0", markdown);
}
}

public void appendMarkdown(String additionalMarkdown) {
this.markdown += additionalMarkdown;
getElement().executeJs("this.markdown.value += $0", additionalMarkdown);
}

public void clear() {
setMarkdown("");
}

public String getMarkdown() {
return markdown;
}
}
112 changes: 112 additions & 0 deletions src/main/java/org/cftoolsuite/ui/component/MetadataFilter.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
package org.cftoolsuite.ui.component;

import com.vaadin.flow.component.button.Button;
import com.vaadin.flow.component.customfield.CustomField;
import com.vaadin.flow.component.grid.Grid;
import com.vaadin.flow.component.icon.VaadinIcon;
import com.vaadin.flow.component.orderedlayout.FlexComponent;
import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
import com.vaadin.flow.component.textfield.TextField;
import org.cftoolsuite.domain.chat.FilterMetadata;

import java.util.ArrayList;
import java.util.List;

public class MetadataFilter extends CustomField<List<FilterMetadata>> {
private final Grid<MetadataEntry> grid;
private final List<MetadataEntry> entries;
private final TextField keyField;
private final TextField valueField;
private final Button addButton;

public MetadataFilter() {
entries = new ArrayList<>();
grid = new Grid<>();

grid.addColumn(MetadataEntry::getKey).setHeader("Key").setFlexGrow(1);
grid.addColumn(MetadataEntry::getValue).setHeader("Value").setFlexGrow(1);
grid.addComponentColumn(this::createRemoveButton).setWidth("100px").setFlexGrow(0);

grid.setItems(entries);

keyField = new TextField("Key");
valueField = new TextField("Value");
addButton = new Button("Add", VaadinIcon.PLUS.create());
addButton.addClickListener(e -> addEntry());

HorizontalLayout inputLayout = new HorizontalLayout(keyField, valueField, addButton);
inputLayout.setWidth("100%");
inputLayout.setAlignItems(FlexComponent.Alignment.END);

VerticalLayout layout = new VerticalLayout(inputLayout, grid);
layout.setSpacing(false);
layout.setPadding(false);
add(layout);
}

private Button createRemoveButton(MetadataEntry entry) {
Button removeButton = new Button(VaadinIcon.TRASH.create());
removeButton.addClickListener(e -> {
entries.remove(entry);
grid.getDataProvider().refreshAll();
updateValue();
});
return removeButton;
}

private void addEntry() {
String key = keyField.getValue().trim();
String value = valueField.getValue().trim();

if (!key.isEmpty() && !value.isEmpty()) {
entries.add(new MetadataEntry(key, value));
keyField.clear();
valueField.clear();
grid.getDataProvider().refreshAll();
updateValue();
}
}

@Override
protected List<FilterMetadata> generateModelValue() {
if (entries.isEmpty()) {
return null;
}

List<FilterMetadata> metadata = new ArrayList<>();
for (MetadataEntry entry : entries) {
metadata.add(new FilterMetadata(entry.getKey(), entry.getValue()));
}
return metadata;
}

@Override
public void setPresentationValue(List<FilterMetadata> metadata) {
entries.clear();
if (metadata != null) {
metadata.forEach(fm ->
entries.add(new MetadataEntry(fm.key(), fm.value()))
);
}
grid.getDataProvider().refreshAll();
}

private static class MetadataEntry {
private final String key;
private final Object value;

public MetadataEntry(String key, Object value) {
this.key = key;
this.value = value;
}

public String getKey() {
return key;
}

public Object getValue() {
return value;
}
}
}
Loading

0 comments on commit 7843ba3

Please sign in to comment.